django ajax: User matching query does not exist - javascript

So I made a django ajax that everytime there is a new message the notification object that I add to my user models will be +1, the problem is that I dont know why is giving me this error:
django.contrib.auth.models.User.DoesNotExist: User matching query does not exist.
here is my code:
views.py:
def count_notification(request):
user = request.user
obj = user.profile.objects.get(pk=1)
obj.notifications = obj.notifications +1
obj.save()
response_data = {'success':1}
return HttpResponse(json.dumps(response_data), content_type="application/json")
urls.py:
path('messages/notification/', count_notification)
html file js
// Add the notification val
$.get('notification/')
models.py:
class ProfileImage(models.Model):
"""
Profile model
"""
user = models.OneToOneField(
verbose_name=_('User'),
to=settings.AUTH_USER_MODEL,
related_name='profile',
on_delete=models.CASCADE
)
avatar = models.ImageField(upload_to='profile_image')
notifications = models.FloatField(default='0')
thank you for the help

obj = user.profile.objects.get(pk=1)
i think your app is dealing with many users, each user has its own profile with its own notification count, so why you are fixing the id / pk to 1, you need to get the related profile, not hard code the id
try this code below
def count_notification(request):
user = request.user
user.profile.notifications += 1
user.profile.save()
response_data = {'success':1}
return HttpResponse(json.dumps(response_data), content_type="application/json")
and change
notifications = models.FloatField(default='0')
to
notifications = models.IntegerField(default='0')
it does make more sens since notifications count is an integer not float nand don't forget to rerun migrations
Update
i guess you have not defined a custom User model in settings.py in this case you need to make some changes in models.py
refer to https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#reusable-apps-and-auth-user-model
from django.contrib.auth import get_user_model # get the default User model
User = get_user_model()
class ProfileImage(models.Model):
"""
Profile model
"""
user = models.OneToOneField(
verbose_name=_('User'),
# to=settings.AUTH_USER_MODEL, # you don't need this since you didn't
# defined a custom User model in
# setting.py
to = User, # HERE
related_name='profile',
on_delete=models.CASCADE
)
avatar = models.ImageField(upload_to='profile_image')
notifications = models.IntegerField(default='0') # change the field type
Update 2
from django.contrib.auth import get_user_model
User = get_user_model()
..
def count_notification(request):
# user = request.user
user = User.objects.filter(id=request.user.id).first() # HERE
user.profile.notifications += 1
user.profile.save()
response_data = {'success':1}
return HttpResponse(json.dumps(response_data), content_type="application/json")

Related

How to solve add key and value in cookies in the developer tools using django?

This is a Social network website. It's built-in python Django. I need to add the user login section to the values stored in the local storage section.
in this website have 2 login method one is end-user and another is companies
the main setting is needed user is login that time the key and value is needed to store the local storage
this is needed for cross-site login for users for example Facebook users have joined in through Instagram.
please help me with the solution? I need to fix the set cookies in the session also
I added the codes below section models.py
# Custom user
class CustomUser(AbstractUser):
""" Custom user model"""
email = models.EmailField(unique=True, validators=[EmailValidator])
is_company = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
is_enduser = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
slug = AutoSlugField(populate_from='username')
objects = CustomUserManager()
def __str__(self):
return f"{self.username}"
#property
def group_name(self):
"""
Returns a group name based on the user's id to be used by Django Channels.
Example usage:
user = User.objects.get(pk=1)
group_name = user.group_name
"""
return "user_%s" % self.id
*urls.py
app_name = 'account'
urlpatterns = [
path('login/company/', views.u_login, name='c_login'),
path('login/employee/', views.c_login, name='u_login'),
path('logout/', views.user_logout, name='logout'),
path('user-signup/', user_signup_view, name="user_signup"),
path('switch/<int:id>/', switch_user, name="user_switch"),
path('activate/<slug:uidb64>/<slug:token>/',views.activate_account, name='activate'),
path('change-pwd/<int:id>/', views.set_password, name='set_pwd'),
]
#employee copy login
def c_login(request):
print("runned")
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
print("cd",cd)
user = authenticate(request,
username=cd['username'],
password=cd['password'],
remember_me=cd['remember_me'])
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('feed:user_feed', args=[request.user.profile.slug]))
else:
return HttpResponse('Disabled account')
else:
messages.error(request, 'Invalid username or password')
return render(request, 'account/u_login.html', {'form': form})
else:
form = LoginForm
return render(request, 'account/u_login.html', {'form': form})
Login session check through cookies and set encrypted token with (Unique ID, Name, E-mail) According to the given flow.
Set details in Cookies with Encrypted Token
With
(ID,Name,Email )
Probably django-allauth is what you need. Most thing you need have been implemented.
https://django-allauth.readthedocs.io/en/latest/index.html
first install these packages and the settings include session also.
https://docs.djangoproject.com/en/3.2/topics/http/sessions/
install this package and session need to added also
pip install djangorestframework-simplejwt
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
SESSION_COOKIE_SECURE = False
ENCRYPTED_COOKIE_SERIALIZER = 'json'
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'
COMPRESS_ENCRYPTED_COOKIE = True
ENCRYPTED_COOKIE_COMPRESSION_LEVEL = 1

DFR simple jwt get authToken from a user instance instead of username/password

I have a simple chat app, authentication in it works exaclty as whatsapp
Get phone number => if doesn't exist create one else skip => send validation code and set it as "phone_code" field in User model => finally remove the "phone_code" if validated
The app is built in React Native with Rest framework as the API, I'm new to this and I'm struggling to get the authentication token without the password. i use djangorestframework-simplejwt
my register view:
#api_view(('POST',))
def register(request):
if request.method == 'POST':
serializer = UserSerializer(data=request.data)
if not serializer.is_valid():
if 'is not valid' in serializer.errors['phone_number'][0]:
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
phone_number = serializer.initial_data['phone_number'].replace(' ', '')
try:
user = User.objects.get(phone_number=phone_number)
except User.DoesNotExist:
user = User.objects.create_user(
phone_number=phone_number, username=phone_number)
user.phone_code = randint(99999, 999999)
user.save()
TokenObtainPairView()
return Response(serializer.data, status.HTTP_200_OK)
# todo send validation code, I will handle later
my Login view (Chich validates for the validation code)
#api_view(['POST',])
def loginuser(request):
if request.method == 'POST':
phone_number = request.data.get('phone_number')
try:
user = User.objects.get(phone_number=phone_number)
if int(request.data.get('phone_code')) == user.phone_code and user.phone_code:
user.phone_code = None
user.save()
#!!!!!!!!!!!!!!!!!!!NOW HOW CAN I GET THE JWT AUTHENTICATION TOKEN AND SEND IT TO MY REACT NATIVE APP?!
return JsonResponse({'phone_number': phone_number}, status=200)
else:
return JsonResponse({'error': "Invalid code"}, status=400)
except Exception as error:
return JsonResponse({'error': error}, status=500)
when the user validates his phonenumber, how can I send the jwt format auth token with the Response?
urls.py:
path('api/token/', users_views.ObtainToken.as_view(), name='token_obtain_pair'),
my Custom obtainToken view:
class ObtainToken(TokenObtainPairView):
permission_classes = (AllowAny,)
serializer_class = MyTokenObtainPairSerializer
Also I found out that when I was using Postman if I send an empty password the system will give a the authentication token. I would appreciate any help, thanks
You should base your code on the existing views and serialiazer from rest_framework_simplejwt : using TokenObtainPairView is a good start, keep that.
Then in your seriliazer_class, MyTokenObtainPairSerializer, you should use TokenObtainSerializer
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
self.user = User.objects.get(phone_number=phone_number)
# Do the verification with the phone_code here, if error, return a response with an error status code
refresh = self.get_token(self.user)
data['refresh'] = text_type(refresh)
data['access'] = text_type(refresh.access_token)
return data

Issue with django rest framework when creating new objects

I am trying to use django rest framework to create instances of a Bookmark model for different types of content, for example Book.
The code:
models.py
class Bookmark(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
api.py
from django.contrib.contenttypes.models import ContentType
from rest_framework import viewsets, mixins, serializers, permissions
from .models import Bookmark
class BookmarkSerializer(serializers.ModelSerializer):
class Meta:
model = Bookmark
fields = ('id', 'user', 'content_type', 'object_id')
class BookmarkViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
queryset = Bookmark.objects.all()
serializer_class = BookmarkSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
content_type = self.request.query_params.get('content_type')
app, model = content_type.split(".")
ct = ContentType.objects.get_by_natural_key(app, model)
object_id = self.request.query_params.get('object_id')
serializer.save(user=self.request.user, content_type=ct, object_id=object_id)
def get_queryset(self):
items = Bookmark.objects.filter(user=self.request.user)
content_type = self.request.query_params.get('content_type', None)
if content_type:
app, model = content_type.split(".")
ct = ContentType.objects.get_by_natural_key(app, model)
items = items.filter(content_type=ct)
object_id = self.request.query_params.get('object_id', None)
if object_id:
items = items.filter(object_id=object_id)
return items
get_queryset part is fine. But perform_create fails when I try to create a new Bookmark:
var item = new Bookmark({'content_type': 'books.book', 'object_id': self.book_id});
item.save();
The response:
{"user":["This field is required."],"content_type":["Incorrect type. Expected pk value, received unicode."]}
It is not clear to me how I am supposed to do this. I would appreciate any feedback.
You should post your model definition as well, but the error you are getting is saying that you also need to pass a user argument to Bookmark and that you should be passing a pk value (aka an integer that is the id of the object you're pointing to) for content_type.
I can't say anything about the error message concerning the user, but here is my 2 cents about the second one.
You do not simply give a path to your model as a string to the content_type key.
Apparently
, you have to use the get_for_model method which is passed as parameter a model (The model 'Book', not an instance of it), and returns an object of type ContentType. This object's id is what you should pass as a value.
Both previous answers pointed me in the right direction. In the end, the solution was not to override perform_create, but create function:
def create(self, request, *args, **kwargs):
content_type = request.data['content_type']
if content_type:
app, model = content_type.split(".")
ct = ContentType.objects.get_by_natural_key(app, model)
request.data['user'] = request.user.id
request.data['content_type'] = ct.id
#object_id already passed as id in request.data
A further explanation can be read here:
https://github.com/encode/django-rest-framework/issues/3470

no attribute '_meta' error when trying to run method to delete a row from a URL called by .get()

It's a part of project in django framework.
In a javascript file I'm writing a code segment to .get() a URL
e.g. /delete/student/<id_of_student> .
.
.
$.get($(this).attr('href'), location.reload(true), function(data){ alert("Put in bin !!"); });
.
.
When it will be called , from urls.py it will be mapped to a function which will put the row in trash_bin and from page the row will be deleted after reload.
But in runserver console it's throwing error like:
concrete_model = model._meta.concrete_model
AttributeError: type object 'builtin_function_or_method' has no attribute '_meta'
But in console.log showing correct url, say /delete/student/123.
Here's the trash part from models.py :
class TrashAction(models.Model):
user = models.ForeignKey(User)
timestamp = models.DateTimeField()
def __unicode__(self):
return "%d items by %s on %s" % (self.trashitem_set.count(), self.user, self.timestamp.strftime('%Y-%m-%d %H:%M'))
class TrashItem(models.Model):
json_data = models.TextField()
contenttype = models.ForeignKey(ContentType)
action = models.ForeignKey(TrashAction)
def __unicode__(self):
data = json.loads(self.json_data)[0]
return "%s[%d]" % (data['model'], data['pk'])
Here's view of trash.py :
def move_to_trash(request, obj):
"""
Moves an object to the trash bin.
"""
c = Collector(using='default')
c.collect([obj])
action = None
with transaction.atomic():
action = TrashAction()
action.user = request.user
action.timestamp = datetime.now()
action.save()
for i in c.instances_with_model():
item = TrashItem()
item.action = action
item.contenttype = ContentType.objects.get_for_model(i[1])
item.json_data = serializers.serialize('json', [ i[1] ])
item.save()
obj.delete()
def delete_product(request, student_id):
move_to_trash(request, id)
Could anybody please help me to understand why this error is coming?

Django/jQuery Cascading Select Boxes in Admin

I have a Contract class where contract_mod allows to extend a contract from a previous one. contract_mod should only show contracts related with the person that we selected previously.
The Contract class returns the field person. As I've never work with AJAX/jQuery I don't know where to start.
So, my goal is that the field contract_mod depends on hte field person (using the Admin interface).
class Contract(models.Model):
person = models.ForeignKey(Person) #person hired
contract_mod = models.OneToOneField('self', blank = True, null = True) #allows to extend a contract
...
As the field contract_mod is OneToOneField I can't use django-smart-selects or django-ajax-select
In a similar situation I did the following (now adapted to your model):
models
class Person(models.Model):
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
def get_name(self):
return self.name
class Contract(models.Model):
person = models.ForeignKey(Person) #person hired
contract_mod = models.OneToOneField('self', blank = True, null = True)
contract_name = models.CharField(max_length=20) #just for testing
def __unicode__(self):
return self.get_name() + " " +self.contract_name
def get_name(self):
return self.person.get_name() #to make sure you get the person name in the admin
def contract_mod_name(self):
if self.contract_mod:
return self.contract_mod.contract_name
else:
return ""
admin
class SelectField(forms.ChoiceField):
def clean(self, value):
return value
class CForm(forms.ModelForm):
contracts_from_selected = SelectField()
class Meta:
model = Contract
widgets = { 'contract_mod' : forms.widgets.Select(attrs={'hidden' : 'true'}) }
class CAdmin(admin.ModelAdmin):
form = CForm
list_display = ('contract_name','get_name','contract_mod_name')#what you like
def save_model(self, request, obj, form, change):
if request.POST.get('contracts_from_selected'):
obj.contract_mod=Contract.objects.get(id=int(request.POST.get('contracts_from_selected')))
obj.save()
Override the change_form.html template (by copying it from the django/contrib/admin/templates/admin into your yourapp/templates/admin/yourapp directory) and add the following Javascript:
$(function () {
$("#id_person").change(function () {
var options = $("#id_contract_mod option").filter(function () {
return $(this).html().split(" ")[0] === $("#id_person option:selected").html();
}).clone();
$("#id_contracts_from_selected").empty();
$("#id_contracts_from_selected").append(options);
});
});
One shortcoming is, that this uses the visible html entry to store the person - contract relation. So the person is also visible in the dropdown. To avoid this you could add an attribute to the options instead - see here:
Django form field choices, adding an attribute
Yes and it would be good to completely hide the contract_mod ChoiceField. Via the hidden=True in the widget only the dropdown is hidden.

Categories