Python Django | POST method with nested object. NOT NULL constraint failed - python

My point is to implement the post method with a nested object which has just ID. When I use all fields of a nested object post method works fine. But I'd like to pass just one field and it is ID, other fields gotta be unrequired
Now I'm getting the error like
NOT NULL constraint failed: article_article.author_id
models.py
class Author(models.Model):
first_name = models.CharField(max_length=20, blank=True, null=True)
last_name = models.CharField(max_length=20, blank=True, null=True)
nickname = models.CharField(max_length=20, blank=True, null=True)
def __str__(self):
return self.nickname
class Article(models.Model):
title = models.CharField(max_length=120, unique=True)
description = models.TextField(blank=True)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='articles')
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, blank=True)
def __str__(self):
return self.title
views.py
class ArticleView(APIView):
def get(self, request, pk=None):
if pk:
article = Article.objects.get(pk=pk)
serializer = ArticleSerializer(article, many=False)
else:
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
def post(self, request):
data = request.data
serializer = ArticleSerializer(data=data)
if serializer.is_valid(raise_exception=True):
article_saved = serializer.save()
return Response({"success": "Article '' created successfully".format(article_saved.title)},
status=status.HTTP_201_CREATED)
serializers.py
class AuthorSerializer(serializers.Serializer):
first_name = serializers.CharField(required=False)
last_name = serializers.CharField(required=False)
nickname = serializers.CharField(required=False)
class ArticleSerializer(serializers.Serializer):
title = serializers.CharField(max_length=120)
description = serializers.CharField()
author = AuthorSerializer(required=False)
def create(self, validated_data):
author_data = validated_data.pop('author', None)
if author_data:
author = Author.objects.get_or_create(**author_data)[0]
validated_data['author'] = author
return Article.objects.create(**validated_data)

I got it. I should just have added to a serializer the field ID
class AuthorSerializer(serializers.Serializer):
first_name = serializers.CharField(required=False)
last_name = serializers.CharField(required=False)
nickname = serializers.CharField(required=False)
id = serializers.IntegerField()

Related

drf: serializers.ModelField > How can i get user_id appropriately?

I want to implement the 'user_id' to be automatically saved at the backend without receiving it from the client. (when create object!)
This is my code.
models.py
class User(AbstractUser):
username = None
email = models.EmailField(max_length=255, unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
social_profile = models.URLField(null=True,blank=True)
realname = models.CharField(max_length=50, blank=True)
nickname = models.CharField(max_length=50, null=True, unique=True)
address = models.CharField(max_length=200, blank=True)
phone = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.email
class Item(models.Model):
user_id = models.ForeignKey(User, related_name='item_sets', on_delete=models.CASCADE)
category_id = models.ForeignKey(Category, related_name='item_sets', on_delete=models.DO_NOTHING)
description = models.TextField()
feature = models.TextField()
product_defect = models.TextField()
size = models.CharField(max_length=6)
height = models.DecimalField(max_digits=4, decimal_places=1, default=0)
weight = models.DecimalField(max_digits=4, decimal_places=1, default=0)
condition = models.CharField(max_length=20)
price = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
sold_out = models.BooleanField(default=False)
def __str__(self):
return self.description
view.py
class ItemViewSet(ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
filter_backends = [SearchFilter, OrderingFilter]
search_fields = ['description'] # ?search=
ordering_fields = ['created_at'] # ?ordering=
ordering = ['-created_at']
authentication_classes = (JWTCookieAuthentication,)
# create
def create(self, request, *args, **kwargs):
city = request.data['city']
gu = request.data['gu']
dong = request.data['dong']
if city is not None and gu is not None and dong is not None:
location = Location.objects.get(
Q(city=city) & Q(gu=gu) & Q(dong=dong)
)
else:
return Response(
{"message": "주소정보를 모두 입력해주세요."},
status=status.HTTP_400_BAD_REQUEST
)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
new_item = Item.objects.get(id=serializer.data['id'])
headers = self.get_success_headers(serializer.data)
LocationSet.objects.create(item_id=new_item, location_id=location)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
# here!
def perform_create(self, serializer):
serializer.save(user_id=self.request.user)
serializers.py
class ItemSerializer(serializers.ModelSerializer):
photos = PhotoSerializer(source='photo_sets', many=True, read_only=True)
style_photos = StylePhotoSerializer(source='style_photo_sets', many=True, read_only=True)
user_id = serializers.ModelField(model_field=User()._meta.get_field('id'), required=False) #here!
class Meta:
model = Item
fields = '__all__'
# Photo, StylePhoto
def create(self, validated_data):
images_data = self.context['request'].FILES
item = Item.objects.create(**validated_data)
for photo_data in images_data.getlist('photos_data'):
Photo.objects.create(item_id=item, photo=photo_data)
for style_photo_data in images_data.getlist('style_photos_data'):
StylePhoto.objects.create(item_id=item, user_id=self.context['request'].user,
photo=style_photo_data)
print(User()._meta.get_field('id'))
return item
so I overrided perform_create() in views.py
and write 'user_id = serializers.ModelField(model_field=User()._meta.get_field('id'), required=False)' in serializers.py
but it doesn't work well like my intend...
correct user_id is 8. but my object has 18..:<
18 is just item_id, not user_id..
what should I do to fix this error?
Try this:
views.py : use the perform_create() method to save the user_id.
Note: the user must be authenticated so that we can get them from the request.
class ItemViewSet(ModelViewSet):
# your code ...
# create
def create(self, request, *args, **kwargs):
# your code code ...
def perform_create(self, serializer): # new
serializer.save(user_id=self.request.user)
serializers.py :
Get the user_id from the database and make it readonly as it is not supposed to be edited by the user:
class ItemSerializer(serializers.ModelSerializer):
# your code ..
user_id = serializers.ReadOnlyField(source='user_id.id') # new
class Meta:
model = Item
fields = '__all__'
# Photo, StylePhoto
def create(self, validated_data):
images_data = self.context['request'].FILES
item = Item.objects.create(**validated_data)
for photo_data in images_data.getlist('photos_data'):
Photo.objects.create(item_id=item, photo=photo_data)
for style_photo_data in images_data.getlist('style_photos_data'):
StylePhoto.objects.create(item_id=item,photo=style_photo_data) # new
print(User()._meta.get_field('id'))
return item
I would also recommend you change the user_id field to something like owner to prevent future confusion.

Cannot assign "<SimpleLazyObject: <User: student1#mail.ru>>": "Answer.id_student" must be a "Student" instance

I am trying to use email for authentication in Django. Previously, I worked directly with the user, but I need it through the "Student" class.
VIEWS
class AnswerToCase(FormMixin, DetailView):
STATUS = [
('Участник', 'Участник'), ('Победитель', 'Победитель')]
model = Case
template_name = 'addanswer.html'
form_class = AddAnswer
success_url = '/'
context_object_name = 'get_case'
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.id_case = self.get_object()
What is the correct way to specify saving an object to yourself?
self.object.id_student = self.request.user
self.object.is_won = self.get_object()
self.object.save()
return super().form_valid(form)
If I write the command like this self.object.id_student = Student.objects.get(user_id=self.request.user)
Error
['The value of “Fun” must be True or False.']
Fan is title of the "case" model
Models
Class User
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(db_index=True, unique=True, max_length=254)
phone = models.CharField(max_length=20, help_text='Номер телефона')
is_staff = models.BooleanField(default=True) # must needed, otherwise you won't be at
is_active = models.BooleanField(default=True) # must needed, otherwise you won't be «
is_superuser = models.BooleanField(default=False) # this field we inherit from Permis
is_student = models.BooleanField(default=False)
is_partner = models.BooleanField(default=False)
objects = CustomUserManager()
REQUIRED_FIELDS = ["phone"]
USERNAME_FIELD = 'email'
Class Student
class Student(models.Model):
user = models.OneToOneField(User, verbose_name='id', on_delete=models.CASCADE, primary_key=True)
Fio = models.CharField(max_length=100, blank=True, verbose_name='ФИО')
Educational_institution = models.CharField(max_length=50, verbose_name='Место учебы')
age = models.CharField(max_length=2,verbose_name='возраст')
region = models.CharField(max_length=50, choices=REGIONS, default=REGIONS[0])
Direction_of_study = models.CharField(max_length=50, verbose_name='Специальность')
Education = models.CharField(max_length=50, verbose_name='Образование', choices=EDUCATION, default=EDUCATION[0])
Course = models.CharField(max_length=50, verbose_name='Курс', choices=COURSE, default=COURSE[0])
Class Answer
class Answer(models.Model):
Url = models.URLField(verbose_name='Ссылка на ответ', blank=True)
File = models.FileField(verbose_name='Файл', upload_to = "file",blank=True)
id_case = models.ForeignKey(Case, verbose_name="Кейс", on_delete=models.CASCADE,blank=True,related_name='cases')
If you change the class to User, then saving works id_student = models.ForeignKey(Student, verbose_name="Студент", on_delete=models.CASCADE,blank=True)
id_student = models.ForeignKey(Student, verbose_name="Студент", on_delete=models.CASCADE,blank=True)
is_won = models.BooleanField(default=False)
Class Case
class Case(models.Model):
title = models.CharField(max_length=200, verbose_name='Название')
description = models.TextField(verbose_name='Описание кейса')
date_of_create = models.DateTimeField(auto_now=True, verbose_name='Дата создания')
date_of_edit = models.DateTimeField(auto_now_add=True, verbose_name='Дата последней редакции')
date_of_close = models.DateTimeField(verbose_name='Дата закрытия')
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='Категории')
user_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name='partners')
is_published = models.BooleanField(default=True, verbose_name='Опубликован')

'QuerySet' object has no attribute 'save' Error Occurred

I am a student studying Django. Currently, the member information has been entered in the Member table. I want to create Mypage so that member information registered in the Member table can be modified, and develop so that member information can be modified on Mypage. But while developing, I faced the following error: How can I solve this? Any help would be greatly appreciated.
Detail Error :
AttributeError at /mypage/mypage_modify/
'QuerySet' object has no attribute 'save'
Request Method: POST
Request URL: http://127.0.0.1:8000/mypage/mypage_modify/
Django Version: 3.1.5
Exception Type: AttributeError
Exception Value:
'QuerySet' object has no attribute 'save'
Exception Location: C:\zeronine_project\mypage\views.py, line 27, in mypage_modify
Python Executable: D:\anaconda3\envs\vnv_zn\python.exe
Python Version: 3.7.6
Python Path:
['C:\\zeronine_project',
'D:\\anaconda3\\envs\\vnv_zn\\python37.zip',
'D:\\anaconda3\\envs\\vnv_zn\\DLLs',
'D:\\anaconda3\\envs\\vnv_zn\\lib',
'D:\\anaconda3\\envs\\vnv_zn',
'D:\\anaconda3\\envs\\vnv_zn\\lib\\site-packages']
Server time: Thu, 08 Jul 2021 21:05:53 +0900
view.py
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect
from mypage.forms import *
from zeronine.models import *
# Create your views here.
def mypage_list(request):
categories = Category.objects.all()
return render(request, 'mypage/mypage_list.html', {'categories':categories})
def mypage_modify(request):
current_category = None
categories = Category.objects.all()
member = Member.objects.all()
if not request.user.is_authenticated:
return HttpResponseRedirect(reverse('zeronine:login'))
if request.method == "POST":
member.name = request.POST['name']
member.password = request.POST['password']
member.username = request.user
member.save()
return redirect('zeronine:post')
else:
memberForm = MemberForm
return render(request, 'mypage/mypage_modify.html', {'memberForm':memberForm, 'member':member, 'current_category': current_category, 'categories': categories})
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.urls import reverse
# 회원
class Member(AbstractUser):
username = models.CharField(primary_key=True, max_length=20, verbose_name='아이디')
name = models.CharField(max_length=20, verbose_name='이름', default='')
password = models.CharField(max_length=64, verbose_name='비밀번호')
phone = models.CharField(max_length=64, verbose_name='전화번호')
def __str__(self):
return self.username
class Meta:
verbose_name = ('Member')
verbose_name_plural = ('Members')
# 카테고리
class Category(models.Model):
category_code = models.AutoField(primary_key=True)
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, allow_unicode=True)
class Meta:
ordering =['category_code']
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('zeronine:product_in_category', args=[self.slug])
# 상품
class Product(models.Model):
product_code = models.AutoField(primary_key=True)
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
category_code = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='products')
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, unique=False, allow_unicode=True)
image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
benefit = models.TextField()
detail = models.TextField()
target_price = models.IntegerField()
start_date = models.DateField()
due_date = models.DateField()
class Meta:
ordering = ['product_code']
index_together = [['product_code', 'slug']]
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('zeronine:product_detail', args=[self.product_code, self.slug])
class Post(models.Model):
post_code = models.AutoField(primary_key=True)
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
title = models.CharField(max_length=64)
content = models.TextField()
register_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['register_date']
# 댓글(댓글코드, 게시글코드(fk), 아이디(fk), 내용, 등록날짜)
class Comment(models.Model):
comment_code = models.AutoField(primary_key=True)
post_code = models.ForeignKey(Post, on_delete=models.CASCADE, db_column='post_code')
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
content = models.TextField()
register_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.content
class Meta:
ordering = ['register_date']
# Zzim 모델부터 새로 추가하려는 모델들 입니다.
# 찜하기(찜코드, 아이디(fk), 상품코드(fk))
class Zzim(models.Model):
zzim_code = models.AutoField(primary_key=True)
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
def __str__(self):
return str(self.zzim_code)
# 상품이미지(이미지코드, 상품코드(fk), 이미지경로)
class Photo(models.Model):
photo_code = models.AutoField(primary_key=True)
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
photo = models.ImageField(upload_to="photos/%Y%m%d")
def __str__(self):
return str(self.photo_code)
class Meta:
ordering = ['photo_code']
# 옵션(옵션코드, 옵션명, 상품코드(fk))
class Option(models.Model):
option_code = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
def __str__(self):
return self.name
# 옵션값(옵션값코드, 옵션값명, 옵션코드(fk), 상품코드(fk))
class Value(models.Model):
value_code = models.AutoField(primary_key=True)
option_code = models.ForeignKey(Option, on_delete=models.CASCADE, db_column='option_code')
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
name = models.CharField(max_length=32)
def __str__(self):
return self.name
# 옵션지정상품(옵션지정상품코드, 상품코드(fk), 가격, 참여수량)
class Designated(models.Model):
designated_code = models.AutoField(primary_key=True)
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
price = models.IntegerField()
rep_price = models.BooleanField(default=True)
class Meta:
ordering = ['designated_code']
def __str__(self):
return str(self.designated_code)
# 상품옵션구성(상품옵션구성코드, 옵션지정상품코드, 옵션값코드)
class Element(models.Model):
element_code = models.AutoField(primary_key=True)
designated_code = models.ForeignKey(Designated, on_delete=models.CASCADE, db_column='designated_code')
value_code = models.ForeignKey(Value, on_delete=models.CASCADE, db_column='value_code')
class Meta:
ordering = ['element_code']
def __str__(self):
return str(self.element_code)
# 참여(참여코드, 아이디(fk), 상품코드(fk), 수량)
class Join(models.Model):
join_code = models.AutoField(primary_key=True)
username = models.ForeignKey(Member, on_delete=models.CASCADE, db_column='username')
product_code = models.ForeignKey(Product, on_delete=models.CASCADE, db_column='product_code')
part_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.join_code)
class Meta:
ordering = ['join_code']
#참여상세(참여상세코드, 수량, 가격, 참여코드, 옵션지정상품코드)
class JoinDetail(models.Model):
joindetail_code = models.AutoField(primary_key=True)
join_code = models.ForeignKey(Join, on_delete=models.CASCADE, db_column='join_code')
designated_code = models.ForeignKey(Designated, on_delete=models.CASCADE, null=True, blank=True, db_column='designated_code')
quantity = models.IntegerField()
price = models.IntegerField()
def __str__(self):
return str(self.joindetail_code)
class Meta:
ordering = ['joindetail_code']
You are not specifying a member object to update. member = Member.objects.all() will get a queryset of all the member objects in your database.
Try doing:
def mypage_modify(request):
current_category = None
categories = Category.objects.all()
member = Member.objects.all()
if not request.user.is_authenticated:
return HttpResponseRedirect(reverse('zeronine:login'))
if request.method == "POST":
member = Member.objects.get(name=request.POST['name']) #specifying the member
member.name = request.POST['name']
member.password = request.POST['password']
member.username = request.user
member.save()
return redirect('zeronine:post')
else:
memberForm = MemberForm
return render(request, 'mypage/mypage_modify.html', {'memberForm':memberForm, 'member':member, 'current_category': current_category, 'categories': categories})
Or if you are making a new member object then instead of member = Member.objects.get(name=request.POST['name'])
Do: member = Member()
EDIT:
Not sure why you'd want to do this in practise, but to change every member object in the database you'd do the following:
def mypage_modify(request):
current_category = None
categories = Category.objects.all()
member = Member.objects.all()
if not request.user.is_authenticated:
return HttpResponseRedirect(reverse('zeronine:login'))
if request.method == "POST":
for m in member:
m.name = request.POST['name']
m.password = request.POST['password']
m.username = request.user
m.save()
return redirect('zeronine:post')
What you're accessing with member = Member.objects.all() is a list of Member objects.
To get a desired member use
member = Member.objects.get()
or
member = Member.objects.filter()
In the latter, you'd also need to check
if member:
member = member.first()
Check
https://docs.djangoproject.com/en/3.2/ref/models/querysets/#filter
https://docs.djangoproject.com/en/3.2/ref/models/querysets/#get

How to deserialize nested serializers with Django Rest Framework

i have in models.py
class Variants(Model):
class Meta:
db_table = 'variants'
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, blank=False, null=False)
client = models.ForeignKey(Client, on_delete=models.CASCADE, null=False, blank=False)
created_at = models.DateField(auto_created=True, default=now, blank=True)
updated_at = models.DateField(auto_now=True, null=True, blank=True)
and
class VariantOptions(Model):
class Meta:
db_table = 'variant_options'
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, blank=False, null=False)
variant = models.ForeignKey(Variants, on_delete=models.CASCADE, null=False, blank=False)
created_at = models.DateField(auto_created=True, default=now, blank=True)
updated_at = models.DateField(auto_now=True, null=True, blank=True)
and in serializers.py
class VariantOptionsSerializer(serializers.ModelSerializer):
class Meta:
model = models.VariantOptions
fields = ['name']
class VariantsSerializer(serializers.ModelSerializer):
options = VariantOptionsSerializer(many=True)
class Meta:
model = models.Variants
fields = ['name','client','options']
def create(self, validated_data):
options_data = validated_data.pop('options')
variant = models.Variants.objects.create(**validated_data)
for option_data in options_data:
models.VariantOptions.objects.create(variant=variant, **option_data)
return variant
and my view
class VariantsCreate(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = serializers.VariantsSerializer
def post(self, request, format=None):
serializer = serializers.VariantsSerializer(data=request.data)
if serializer.is_valid():
saved = serializer.save()
return Response(serializer.data) ==> serializer.data gives error
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
i have this error
Got AttributeError when attempting to get a value for field options on serializer VariantsSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Variants instance.
Original exception text was: 'Variants' object has no attribute 'options'.
but the data has already been validated by the call to is_valid()
why return Response(serializer.data) gives error ?
Try to change
variant = models.ForeignKey(Variants, on_delete=models.CASCADE, null=False, blank=False)
with
variant = models.ForeignKey(Variants, related_name='options', on_delete=models.CASCADE, null=False, blank=False)

Insert related field django rest framework

I have this simple model and I am having difficult in inserting related field of 'notes' through django rest framework.
class Student(models.Model):
firstName = models.CharField(max_length=100, blank=True, null=True)
lastName = models.CharField(max_length=100, blank=True, null=True)
prefLocation = models.ManyToManyField("Location", blank=True, null=True, related_name = 'prefLocation')
def __unicode__(self):
return self.firstName
class LocationRegion(models.Model):
regionName = models.CharField(max_length=100)
def __unicode__(self):
return self.regionName
class Location(models.Model):
locationName = models.CharField(max_length=100)
region = models.ForeignKey(LocationRegion, null=True, blank=True, related_name='locations')
def __unicode__(self):
return self.locationName
class Note(models.Model):
text = models.CharField(max_length=1000)
student = models.ForeignKey(Student, null=True, blank=True, related_name='notes')
def __unicode__(self):
return self.text
class StudentViewSet(viewsets.ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
I am unsure if I need to use ModelSerializer or generic Serializer. Validated_data doesn't return 'note' field in the deserialized data. I would appreciate any help with the serializer.
Thanks
Here are my serializers :
class StudentSerializer(serializers.ModelSerializer):
def create(self, validated_data):
def get_notes(self, obj):
return validated_data['note']
note = serializers.SerializerMethodField('get_notes')
return Candidate.objects.create(**validated_data)
class Meta:
model = Student
fields = ('id', 'firstName', 'lastName', 'note')
class NoteSerializer(serializers.ModelSerializer):
class Meta:
model = Note

Categories

Resources