Django Rest Framework Not Null Constraint - django

When i try to create a new by post by posting the following Json:
{
"title": "This is serialzer title",
"content": "This is serialzer content",
}
I get the following error:
NOT NULL constraint failed: blog_post.views
Models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils.timezone import now
# Create your models here.
class Post(models.Model):
sno = models.AutoField(primary_key=True)
title = models.CharField(max_length=255)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
views = models.IntegerField()
slug = models.CharField(max_length=100)
timeStamp = models.DateTimeField(default=now)
def __str__(self):
# return self.title + ' by ' + self.author
return self.title + ' by ' + self.author.username
class BlogComment(models.Model):
sno = models.AutoField(primary_key=True)
comment = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True)
timeStamp = models.DateTimeField(default=now)
def __str__(self):
return self.comment[0:13] + "..." + " by " + self.user.username
views.py
#api_view(['POST'])
def api_create_blog_view(request):
user = User.objects.get(pk=1)
blog_post = Post(author=user)
if request.method == "POST":
serializer = PostSerializer(blog_post, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.py
from blog.models import Post
from rest_framework import serializers
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['title', 'content']
I don't know how to solve this please help me to solve this error.DB has already been cleared. Locations have been created by using the admin interface. I know that the issue is something trivial, but I just can't get it to work.

You need to set a value for the views. You can do so by specifying a default value:
from django.conf import settings
class Post(models.Model):
sno = models.AutoField(primary_key=True)
title = models.CharField(max_length=255)
content = models.TextField()
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True
)
views = models.IntegerField(default=0)
slug = models.CharField(max_length=100)
timeStamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title + ' by ' + self.author.username
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: According to the PEP-8 Style Guide, the classes should be written in PerlCase, and the fields in snake_case.

Related

Django saveing logged in logged in user as ForeignKey

I have model with a ForeignKey "log_written_by" and I want that to be the logged in user.
How should i state that in my forms.py as a hiddenfield?
class AssetLog(models.Model):
# Relationships
log_written_by = models.ForeignKey("auth.User", on_delete=models.SET_NULL, blank=True, null=True)
asset_case = models.ForeignKey("asset_app.AssetCase", on_delete=models.CASCADE)
# Fields
date_time_log = models.DateTimeField()
notes = models.TextField(max_length=1024)
created = models.DateTimeField(auto_now_add=True, editable=False)
class Meta:
pass
def __str__(self):
return str(self.pk)
def get_absolute_url(self):
return reverse("asset_app_AssetLog_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_AssetLog_update", args=(self.pk,))
You can do the following:
class AssetLogForm(forms.ModelForm):
class Meta:
model = AssetLog
fields = ('log_written_by ', '...,')
widgets = {'log_written_by ': forms.HiddenInput()}
See this related StackOverflow post here.

Save Django Form wizard data to three models with related fields

I am working on a project that requires use of form wizard to populate three related models. The first model - Listing - has general data which has a OneToOneField relationship with the second model (Property). The Listing model also has a many to many relationships with the third model (ListingImages). In general, I am using 4 forms in the wizard. Here is the models definition
models.py
class Listing(models.Model):
listing_type_choices = [('P', 'Property'), ('V', 'Vehicle'), ('B', 'Business/Service'), ('E', 'Events')]
listing_title = models.CharField(max_length=255)
listing_type = models.CharField(choices=listing_type_choices, max_length=1, default='P')
status = models.BooleanField(default=False)
featured = models.BooleanField(default=False)
city = models.CharField(max_length=255, blank=True)
location = PlainLocationField(based_fields=['city'], zoom=7, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
expires_on = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(User,
on_delete=models.CASCADE, editable=False, null=True, blank=True
)
listing_owner = models.ForeignKey(User,
on_delete=models.CASCADE, related_name='list_owner'
)
def __str__(self):
return self.listing_title
def get_image_filename(instance, filename):
title = instance.listing.listing_title
slug = slugify(title)
return "listings_pics/%s-%s" % (slug, filename)
class ListingImages(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE)
image_url = models.ImageField(upload_to=get_image_filename,
verbose_name='Listing Images')
main_image = models.BooleanField(default=False)
class Meta:
verbose_name_plural = "Listing Images"
def __str__(self):
return f'{self.listing.listing_title} Image'
class Property(models.Model):
sale_hire_choices = [('S', 'Sale'), ('R', 'Rent')]
fully_furnished_choices = [('Y', 'Yes'), ('N', 'No')]
listing = models.OneToOneField(Listing, on_delete=models.CASCADE)
sub_category = models.ForeignKey(PropertySubCategory, on_delete=models.CASCADE)
for_sale_rent = models.CharField(choices=sale_hire_choices, max_length=1, default=None)
bedrooms = models.PositiveIntegerField(default=0)
bathrooms = models.PositiveIntegerField(default=0)
rooms = models.PositiveIntegerField(default=0)
land_size = models.DecimalField(max_digits=10, decimal_places=2)
available_from = models.DateField()
car_spaces = models.PositiveIntegerField(default=0)
fully_furnished = models.CharField(choices=fully_furnished_choices, max_length=1, default=None)
desc = models.TextField()
property_features = models.ManyToManyField(PropertyFeatures)
price = models.DecimalField(max_digits=15, decimal_places=2)
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Here is the forms.py
from django import forms
from .models import Listing, Property, Vehicle, Business, ListingImages
from django.forms import modelformset_factory
class ListingDetails(forms.ModelForm):
class Meta:
model = Listing
fields = ['listing_title', 'city', 'location']
class PropertyDetails1(forms.ModelForm):
class Meta:
model = Property
fields = ['sub_category', 'for_sale_rent', 'bedrooms', 'bathrooms',
'rooms', 'land_size', 'available_from', 'car_spaces', 'fully_furnished',
'desc', 'currency', 'price'
]
class PropertyDetails2(forms.ModelForm):
class Meta:
model = Property
fields = ['property_features']
class ListingImagesForm(forms.ModelForm):
image_url = forms.ImageField(label='Listing Image',
widget=forms.ClearableFileInput(attrs={'multiple': True}),
required=False
)
class Meta:
model = ListingImages
fields = ['image_url']
ImageFormSet = modelformset_factory(ListingImages, form=ListingImagesForm, extra=3)
views.py
from django.shortcuts import render, redirect
import os
from .forms import ListingDetails, PropertyDetails1, PropertyDetails2, ListingImagesForm
from .models import ListingImages, Listing, Property
from formtools.wizard.views import SessionWizardView
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.forms import modelformset_factory
from django.contrib import messages
from django.http import HttpResponseRedirect, HttpResponse
from django.forms.models import construct_instance
class PropertyView(SessionWizardView):
# formset = ImageFormSet(queryset=Images.objects.none())
template_name = "listings/create_property.html"
form_list = [ListingDetails, PropertyDetails1, PropertyDetails2, ListingImagesForm]
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'media'))
def done(self, form_list, **kwargs):
listing_instance = Listing()
property_instance = Property()
listing_instance.created_by = self.request.user
listing_instance.listing_owner = self.request.user
listing_instance.listing_type = 'P'
for form in form_list:
listing_instance = construct_instance(form, listing_instance, form._meta.fields, form._meta.exclude)
property_instance = construct_instance(form, property_instance, form._meta.fields, form._meta.exclude)
listing = listing_instance.save()
property_instance.listing = listing
property_instance.save()
return HttpResponse('data saved successfully')
The problem that I am facing is that I am able to save the Listing model, but getting its primary id and using it to save the Property model is the problem. Again, the ListingImages model stores images related to the Listing model. How do I save these models to database considering that they are multiple?
What's wrong is that as described here, model.save() does not return the saved object, but None.
So the last few lines of the above code should be
listing_instance.save()
property_instance.listing = listing_instance
property_instance.save()
return HttpResponse('data saved successfully')
Ditto saving a set of listing_images would be something like
for li_obj in listing_image_instances:
li_obj.listing = listing_instance # saved above
li_obj.save()

Not getting foreign key data in django api views

Currently I have a site, and I want the user to be able to view their liked articles. I want this to be included in the user api view that is already set up. I have tried the tracks = serializers.StringRelatedField(many=True)that is in the drf docs yet this didn't work. I have also tried the following:
from rest_framework import serializers
from articles.models import Article, CustomUser,FavoriteArticles
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('title', 'content')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = '__all__'
class FavoriteArticleSerializer(serializers.ModelSerializer):
class Meta:
model = FavoriteArticles
fields = '__all__'
class UserProfileSerializer(serializers.ModelSerializer):
fav_title = FavoriteArticleSerializer(read_only=False)
class Meta:
model = CustomUser
fields = 'username, git, email, fav_article, fav_title, homepage'
and my models:
from django.db import models
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save
from django.dispatch import receiver
import uuid
class ProgrammingLanguage(models.Model):
programming_language = models.CharField(max_length=120, null=False, primary_key=True, default="React")
def __str__(self):
return self.programming_language
class Article(models.Model):
title = models.CharField(max_length=25, primary_key=True)
content = models.TextField()
usedfor = models.TextField()
url=models.CharField(max_length=200, null=True)
article_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="article_programming_language", default="react")
score = models.IntegerField(max_length=5, null=0)
def __str__(self):
return self.title
class CustomUser(AbstractUser):
username = models.CharField(max_length=50, unique=True, primary_key=True)
git = models.CharField(max_length=200, null=True)
homepage = models.CharField(max_length=250, null=True)
user_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="most_used_programming_language", default="react")
def __str__(self):
return str(self.username)
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='fav_title')
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name="user", default="tom" )
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
I think you misunderstood what related_name means. It specifies how you would access a model from its reverse relationship. So I'd recommend you remove it from fields in your FavoriteArticles model and use the default Django already provides (in this case favoritearticles_set):
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE)
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default="tom")
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
This way, you can access favorite articles of a user via my_user.favoritearticles_set.all(). Then, you can change your UserSerializer to include a liked_articles field which is populated from the favoritearticles_set reverse relationship to a user's FavoriteArticles using a source attribute:
class UserSerializer(serializers.ModelSerializer):
liked_articles = FavoriteArticleSerializer(source='favoritearticles_set', many=True, read_only=True)
class Meta:
model = CustomUser
# explicitly include other fields as required
fields = ('username', 'git', 'user_programming_language', 'liked_articles')
Note that we've made this a read_only field, so it will only get populated if you perform a GET request.

Django - Return full_name from Profile model which has relation with Django User model in other model

I created Book, Book_stat a Profile model which has relation with Django User Model, i am trying to display Book title and full_name from Profile as default str return string from Book_stat
models.py
from django.db import models
from django.contrib.auth.models import User
from decimal import Decimal
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=200)
def __str__(self):
return self.title
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
full_name = models.CharField(max_length=150)
def __str__(self):
return self.full_name
class Book_stat(models.Model):
user = models.ForeignKey(User)
book = models.ForeignKey(Book)
rating = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal('0.00'))
like = models.BooleanField(default=False)
def __str__(self):
return self.book.title # here i would like to return book title + full_name from Profile Model
admin.py
from django.contrib import admin
from .models import Book, Book_stat, Profile
# Register your models here.
admin.site.register(Book)
admin.site.register(Book_stat)
admin.site.register(Profile)
When i click on Book_stat in my django admin page i would like to display Book title and Profile full_name as title's in my Book_stat list
def __str__(self):
return self.book.title +' '+ self.user.profile.full_name
try this hope you will get it
Try this:
In your Profile model add related_name like this:
class Profile(models.Model):
user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE)
full_name = models.CharField(max_length=150)
def __str__(self):
return self.full_name
And in your BookStat model:
class Book_stat(models.Model):
user = models.ForeignKey(User)
book = models.ForeignKey(Book)
rating = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal('0.00'))
like = models.BooleanField(default=False)
def __str__(self):
return self.book.title + " - " + self.user.profile.full_name
class Book_stat(models.Model):
user = models.ForeignKey(User)
book = models.ForeignKey(Book)
rating = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal('0.00'))
like = models.BooleanField(default=False)
def __str__(self):
return str(self.book.title) + " : " + str(self.user.get_full_name()) ## changes done here

Django user model, backward look up is not working

I've made a foreign key relationship with django User model, the forward lookup is working fine but when I try to backward is throwing this error:
'QuerySet' object has no attribute 'urlpost_set'
I have also tried the related name! Also note that the Catagory to PostUrl and PostUrl to Catagory is working just fine!
My models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Catagory(models.Model):
title = models.CharField(max_length=15, unique=True)
created = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
def __str__(self):
return self.title
class Meta:
verbose_name_plural = 'catagory'
class UrlPost(models.Model):
STATUS_CHOICES = (
('public', 'Public'),
('private', 'Private'),
)
profile = models.ForeignKey(User, related_name='user_post', on_delete=models.CASCADE)
catagory = models.ForeignKey(Catagory, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
url = models.URLField()
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='public')
note = models.TextField(blank=True)
created = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
class Meta:
ordering = ['-created']
verbose_name_plural = 'url Post'
def __str__(self):
return self.title
You have set related_name='user_post' while defining ForeignKey relation between your User model and UrlPost.
You have to use .user_post.all() instead of .urlpost_set.all() in your queryset.