Value Error: Cannot query "post": Must be "UserProfile" instance - python

I am getting the Value Error: Cannot query "post": Must be "UserProfile" instance when I make a get request to call PostListView.as_view().
Here is my model.py :
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
username = models.CharField(max_length=30)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
password = models.CharField(max_length=100)
def __str__(self):
return self.user.username
class Post(models.Model):
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
views.py :
class PostListView(ListAPIView):
serializer_class = PostSerializer
permission_classes = [AllowAny]
def get_queryset(self):
"""Returns only the object related to current user"""
user = self.request.user
return Post.objects.filter(user=user)
Also, I want a Foreign key relationship exists between User and Post on Model-level, not on the Database level.

user is UserProfile instance but request.user is a User instance
change this line like that to refernece to userprofile
user = self.request.user.userprofile

Related

Like system in Django

I'm trying to implement a like system in Django, but I'm getting FOREIGN KEY constraint failed error
models.py
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="likes")
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="likes")
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username} {self.article.Title}"
class Meta:
ordering = ('-created_at',)
views.py
def like(request, slug, pk):
if request.user.is_authenticated:
try:
like = Like.objects.get(article__slug=slug, user_id=request.user.id)
like.delete()
except:
Like.objects.create(article_id=pk, user_id=request.user.id)
return redirect('blog:article_detail', slug)
urls.py
path('like/<slug:slug>/<int:pk>', views.like, name='like_article')

How to make a permission for checking the Model only can be update by the belonged users?

The below is my code about model Domain's Update:
serializer.py:
class DomainUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Domain
fields = "__all__"
models.py:
class Domain(models.Model):
domain_name = models.CharField(max_length=512, help_text='domain. eg.example.com')
cname = models.ForeignKey(
unique=True,
to=CNAMEModel,
on_delete=models.DO_NOTHING,
related_name="domains",
help_text="CNAME")
ssl_cert = models.TextField(max_length=40960, help_text="SSL cert + ca-bundle")
ssl_key = models.TextField(max_length=40960, help_text="SSL key")
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True)
def __str__(self):
return self.domain_name
def __unicode__(self):
return self.domain_name
class Meta:
verbose_name = "domain"
verbose_name_plural = "domain"
ordering = ['ctime']
class CNAMEModel(models.Model):
name = models.CharField(max_length=64, unique=True, help_text=". eg:gat.demo.com")
desc = models.CharField(max_length=5120, null=True, blank=True, help_text="desc")
desc_en = models.CharField(max_length=5120, null=True, blank=True")
user = models.OneToOneField(unique=True, to=AuthUser, on_delete=models.DO_NOTHING, help_text="belong user")
is_active = models.BooleanField(default=True)
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def __unicode__(self):
return self.name
class Meta:
verbose_name = "CNAME"
verbose_name_plural = "CNAME"
ordering = ['ctime']
views.py:
class DomainUpdateAPIView(UpdateAPIView):
serializer_class = DomainUpdateSerializer
permission_classes = [IsAuthenticated, IsAdminUser]
queryset = Domain.objects.all()
You see Domain belong to CNAME, CNAME belong to a user.
I have a question, how can I make a permission for checking the Domain only can be update by the belonged users or AdminUser(IsAdminUser have solved)?
Or use other way rather than permission.
You can have a additional custom permission:
from rest_framework import permissions
from rest_framework.exceptions import PermissionDenied
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow creator of an object to edit it.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions are only allowed to the creator of the movie
return obj.cname.user == request.user
And in the views IsOwnerOrReadOnly can be included:
from .permissions import IsOwnerOrReadOnly
class DomainUpdateAPIView(UpdateAPIView):
serializer_class = DomainUpdateSerializer
permission_classes = [IsAuthenticated, IsAdminUser, IsOwnerOrReadOnly]
queryset = Domain.objects.all()

How to filter ManyToManyField in django rest framework

I have a model Offlinecheckout and CartItem model. I want to add a filter queryset of the cart field in the offline checkout model. As It is showing the cart of all users. I want to filter queryset by request.user.So that cart filed will show in the cart request.user only not other users.
How I can add a filter in that field.
Models.py
class OfflineCheckOut(models.Model):
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
cart = models.ManyToManyField('cart.CartItem')
time_slot = models.ForeignKey('category.TimeSlot', on_delete=models.CASCADE)
state = models.CharField(max_length=254)
city = models.CharField(max_length=254)
address = models.CharField(max_length=254)
landmark = models.CharField(max_length=254, blank=True)
# order_id = models.ForeignKey('cart.CartModel', on_delete=models.CASCADE)
date = models.DateField()
tsn_amount = models.IntegerField()
def __str__(self):
return self.user.username
class CartItem(models.Model):
cart = models.ForeignKey('CartModel', on_delete=models.CASCADE)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
service = models.ForeignKey('accounts.SubCategory', on_delete=models.CASCADE)
defects = models.ForeignKey('category.Defects', on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
price = models.IntegerField()
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now_add=True)
serializers.py
from rest_framework import serializers
from .models import Address, Date, OfflineCheckOut
class OfflineSerializer(serializers.ModelSerializer):
class Meta:
model = OfflineCheckOut
fields = "__all__"
views.py
class offlineViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
def get_queryset(self):
user = self.request.user
if user.is_authenticated:
if user is not None:
if user.is_active and user.is_superuser or user.is_Customer:
return OfflineCheckOut.objects.all()
raise PermissionDenied()
raise PermissionDenied()
raise PermissionDenied()
serializer_class = OfflineSerializer
You can filter relations by using FilteredRelation in Django
Please change your views.py as follow
from django.db.models import FilteredRelation, Q
class offlineViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
def get_queryset(self):
user = self.request.user
if user.is_authenticated:
if user is not None:
if user.is_active and user.is_superuser or user.is_Customer:
### Use filtered relation
return OfflineCheckOut.objects.filter(user=user).annotate(user_cart=FilteredRelation('cart', condition=Q(cart__user=user)))
raise PermissionDenied()
raise PermissionDenied()
raise PermissionDenied()
serializer_class = OfflineSerializer
I hope this will help you to resolve an issue.
Please refer FilteredRelation objects for more information.
If you require further help please comment

radio buttons incorrectly written to the database in django

I've a registration form, where user must chose one of 2 options.
Django renders all correctly, django admin also have it ok, but db records all possible choices as value.
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','password1','password2']
class UserProfileForm(forms.ModelForm):
terms_compliance = forms.BooleanField(label=mark_safe('I agree with terms and conditions '))
class Meta:
model = UserProfile
widgets = {'role': forms.RadioSelect}
fields = ('role','terms_compliance')
def __init__(self):
self.fields['terms_compliance'].initial = True
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
role_choices = [('publisher','Publisher'), ('advertiser','Advertiser')]
role = models.CharField(max_length=15, choices=role_choices, default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user.username
In new instance (which is user.userprofile.role_choices) I need advertiser or publisher, but all I have is: [('publisher','Publisher'), ('advertiser','Advertiser')]
If you want to provide choices in a Database Field. Do like this:
class UserProfile(models.Model):
class RoleChoice(ChoiceEnum):
PUBLISHER = 'Издатель'
ADVERTISER = 'Рекламодатель'
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.CharField(max_length=15, choices=RoleChoice.choices(), default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user
In Views.py, populate the DB like this.
For example:
...
choice = request.query_params.get('choice') or UserProfile.RoleChoice.PUBLISHER.value
...
For more details read from here: https://django-mysql.readthedocs.io/en/latest/model_fields/enum_field.html

How to expand User(AbstractBaseUser) with OnetoOneField?

I want relate my Profile model with User model from class AbstractUserModel with OnetoOneFields. Is it possible? Or any solution with this problem. Here my models.py
from django.db import models
#from django.contrib.auth.models import User
from django.contrib.auth.models import (
AbstractBaseUser
)
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
class Profile(models.Model):
#HERE
user = models.OneToOneField(AbstractBaseUser, on_delete=models.CASCADE)
nama_lengkap = models.CharField(max_length=100, blank=True, null=True)
tgl_lahir = models.DateField(null=True, blank=True)
alamat = models.CharField(max_length=255)
foto_profil = models.ImageField(upload_to='foto_profil',blank=True)
jabatan = models.ForeignKey(Jabatan, on_delete=models.CASCADE)
def __str__(self):
return "{} - {}".format(self.user, self.nama_lengkap)
when I migrate this, just show some errors message like this:
SystemCheckError: System check identified some issues:
ERRORS:
users.Profile.user: (fields.E300) Field defines a relation with model 'AbstractBaseUser', which is either not installed, or is abstract.
users.Profile.user: (fields.E307) The field users.Profile.user was declared with a lazy reference to 'auth.abstractbaseuser', but app 'auth' doesn't provide model 'abstractbaseuser'.
thanks in advance
you need to replace this
user = models.OneToOneField(AbstractBaseUser, on_delete=models.CASCADE)
with
user = models.OneToOneField(User, on_delete=models.CASCADE)
However I recommend you doing it different way:
Instead of creating second User model, extend existing one:
#models.py
class ProfileUser(AbstractUser):
extra_field = models.CharField(max_length=100)
username = models.CharField(max_length=20) # modifing existing field
```
```
#settings.py
AUTH_USER_MODEL = "app_name.ProfileUser"

Categories

Resources