When I add a new Article, I have a dropdown with a list of all registered users. I want to link the current user to the new Article.
models.py
from django.db import models
from django.conf import settings
User = settings.AUTH_USER_MODEL
class Article(models.Model):
title = models.CharField(max_length=100)
user = models.OneToOneField(User, related_name='Article', on_delete=models.CASCADE)
def __str__(self):
return self.title
serializers.py
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'user']
Here is the solution:
class ArticleSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(
read_only=True, default=serializers.CurrentUserDefault())
class Meta:
model = Article
fields = ['id', 'title', 'user']
def save(self, **kwargs):
kwargs["user"] = self.fields["user"].get_default()
return super().save(**kwargs)
Related
My Django project is based on built-in User model.
For some extra attributes, I have defined another model:
models.py:
class Status(models.Model):
email = models.ForeignKey(User, on_delete=models.CASCADE)
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
def __str__(self):
return self.email
And here's the custom ModelAdmin:
admin.py:
class CustomUserAdmin(UserAdmin):
model = User
list_display = ['email']
search_fields = ['email']
I want list_display to show me is_verified and is_active fields from Status model but I'm lost.
I've looked into some similar questions on SO like Display field from another model in django admin or Add field from another model Django but none of the solutions are applicable because one of my models is Django's built-in.
Try this.
models.py
class Status(models.Model):
# email = models.ForeignKey(User, on_delete=models.CASCADE)
email = models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name='status'
)
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
def __str__(self):
return self.email
admin.py
class CustomUserAdmin(UserAdmin):
model = User
list_display = ['email', 'is_verified', 'is_active']
search_fields = ['email']
def is_verified(self, obj):
return obj.status.is_verified
def is_active(self, obj):
return obj.status.is_active
If you want to apply the displayed name or ordering, please refer to the following
source
I saw your comments and tried running the code myself. There were some problems, so I modified admin.py as follows.
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
admin.site.unregister(User)
#admin.register(User)
class CustomUserAdmin(UserAdmin):
list_display = ['email', 'status_is_verified', 'status_is_active']
list_filter = ['status__is_verified', 'status__is_active']
search_fields = ['email']
#admin.display(ordering='status__is_verified')
def status_is_verified(self, obj):
return obj.status.is_verified
#admin.display(ordering='status__is_active')
def status_is_active(self, obj):
return obj.status.is_active
I am begginer in django. I would like to add some posts and comments but I am getting an Integrity error.
Without comments model it was working before but it doesn´t work together. I already delete my database and makemigrations and migrate again.
post models
from django.db import models
from django.conf import settings
# from django.contrib.auth import get_user_model
# User = get_user_model()
# Create your models here.
class Post(models.Model):
user = models.ForeignKey(
#to=User,
to=settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='posts',
null=True
)
content = models.CharField(
max_length=150,
blank=False
)
created = models.DateTimeField(
auto_now=True
)
liked_by = models.ManyToManyField(
#to=User,
to=settings.AUTH_USER_MODEL,
related_name='liked_posts',
blank=True
)
post serializer
from rest_framework import serializers
from .models import Post
from ..comment.serializers import CommentSerializer
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
comments = CommentSerializer(source='comments.content')
fields = [
'id',
'user',
'content',
'comments',
'created',
'liked_by',
]
comment.models
from django.db import models
from django.conf import settings
from apps.post.models import Post
# Create your models here.
class Comment(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='comment', null=True)
post = models.ForeignKey(to=Post, on_delete=models.SET_NULL, related_name='comment', null=True)
content = models.CharField(max_length=150)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'Comment by: {self.user}'
comment serializer
from rest_framework import serializers
from .models import Comment
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ['id', 'user', 'post', 'content', 'created']
you need to pass the CommentSerializer field in PostSerializer Meta class properly.
from rest_framework import serializers
from .models import Post
from .comment.serializers import CommentSerializer
class PostSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True)
class Meta:
model = Post
fields = [
'id',
'user',
'content',
'comments',
'created',
'liked_by',
'comments',
]
At the moment, I get the user id when I create a new article. I would like also to have the username in the model (I'm using DRF with React, so it would save me a get request just for the username).
models.py:
class Article(models.Model):
title = models.CharField(max_length=100)
user = models.ForeignKey(
User, related_name='Article', on_delete=models.CASCADE)
serializers.py:
class ArticleSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(
read_only=True, default=serializers.CurrentUserDefault())
class Meta:
model = Article
fields = ['id', 'title', 'user']
def save(self, **kwargs):
kwargs["user"] = self.fields["user"].get_default()
return super().save(**kwargs)
The code below should get the username attribute from the user field.
getattr(self.fields['user'], self.fields['user'].USERNAME_FIELD)
Here is the solution:
class ArticleSerializer(serializers.ModelSerializer):
user = PublicProfileSerializer(
read_only=True, default=serializers.CurrentUserDefault())
class Meta:
model = Article
fields = ['id', 'title', 'user']
def save(self, **kwargs):
kwargs["user"] = self.fields["user"].get_default()
return super().save(**kwargs)
with PublicProfileSerializer:
from django.contrib.auth import get_user_model
UserModel = get_user_model()
class PublicProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserModel
fields = [
"id",
"first_name",
"last_name",
"username",
]
I am trying to join two tables and serialize them as an API. I have referred to the docs of the Django rest framework and tried a code. It didn't work. Could not resolve the problem even after trying so many times. I am trying to get a JSON file like
{
'album_name': 'The Grey Album',
'artist': 'Danger Mouse',
'tracks': [
{'order': 1, 'title': 'Public Service Announcement'},
{'order': 2, 'title': 'What More Can I Say'},
{'order': 3, 'title': 'Encore'},
...
],
}
But what I get is
{
'album_name': 'The Grey Album',
'artist': 'Danger Mouse',
}
This is the model file I am using
Model.py
from django.db import models
from django.contrib.auth.models import User
STATUS_CHOICE = (
('simple', 'simple'),
('intermediate', 'intermediate'),
)
class Quiz(models.Model):
quiz_name = models.CharField(max_length=1000)
video_id = models.ForeignKey("youtube.Youtube", on_delete=models.CASCADE)
questions_count = models.IntegerField(default=0)
description = models.CharField(max_length=70, null=True)
created = models.DateTimeField(auto_now_add=True)
slug = models.SlugField()
pass_mark = models.IntegerField()
class Meta:
ordering = ['created']
def __str__(self):
return self.quiz_name
class Category(models.Model):
category = models.CharField(max_length=20, choices=STATUS_CHOICE, default='simple')
quiz_id = models.ForeignKey(Quiz, on_delete=models.CASCADE)
def __str__(self):
return self.category
class Questions(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
question = models.CharField(max_length=1000)
mark = models.IntegerField()
def __str__(self):
return self.question
class Choice(models.Model):
question = models.ForeignKey(Questions, on_delete=models.CASCADE)
choice_1 = models.CharField(max_length=1000)
choice_2 = models.CharField(max_length=1000)
choice_3 = models.CharField(max_length=1000)
choice_4 = models.CharField(max_length=1000)
answer = models.CharField(max_length=1000, default=choice_1)
def __str__(self):
return self.answer
Serializer.py
from rest_framework import serializers
from rest_framework.permissions import IsAuthenticated
from .models import Category, Quiz, Questions, Choice
from django.contrib.auth import authenticate
from django.contrib.auth.hashers import make_password
class QuizSerializer(serializers.ModelSerializer):
class Meta:
model = Quiz
fields = '__all__'
class QuestionsSerializer(serializers.ModelSerializer):
class Meta:
model = Questions
fields = '__all__'
class ChoiceSerializer(serializers.ModelSerializer):
class Meta:
model = Choice
fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
quiz_name = QuizSerializer(read_only=True)
class Meta:
model = Category
fields = ['id','category','quiz_name']
View.py
from rest_framework import generics, permissions, mixins
from rest_framework.response import Response
from .serializer import CategorySerializer
from .models import Category
class ViewQuiz(generics.ListCreateAPIView):
permission_classes = [
permissions.AllowAny,
]
queryset = Category.objects.all()
serializer_class = CategorySerializer
def list(self, request):
queryset = self.get_queryset()
serializer = CategorySerializer(queryset, many=True)
print(serializer.data)
return Response(serializer.data)
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['id','category','quiz_id']
def to_representation(self, instance):
response = super().to_representation(instance)
response['quiz_id'] = QuizSerializer(instance.quiz_id).data
return response
This will produce the result you want, I made an change in how the serializer represent the data. I have some of my serializer doing the same, but my views are working a bit different from yours.
Looks like you are trying to get questions serializes in quiz.
To do that you need to:
1. In Questions model include related_name in quiz field:
class Questions(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name="questions")
question = models.CharField(max_length=1000)
mark = models.IntegerField()
def __str__(self):
return self.question
In QuizSerializer include questions field and set many to True:
class QuizSerializer(serializers.ModelSerializer):
questions = QuestionsSerializer(source="questions", many=True)
class Meta:
model = Quiz
fields = ("questions", ... other needed fields)
Include source attribute in QuizSerializer in CategorySerializer:
class CategorySerializer(serializers.ModelSerializer):
quiz_name = QuizSerializer(read_only=True, source="quiz_id")
class Meta:
model = Category
fields = ['id', 'category', 'quiz_name']
Your Quiz was not serialized because the relation between Category and Quiz in tables are called quiz_id but your field is called quiz_name, so the framework did not know where it should take quiz, because it was looking at quiz_name relation which does not exist.
So I have a model fie, a forms.py file and a views.py file. The views file returns a detail view of a post, now I wish to add a model form of a comments model into the detail view so I can access it in d template as {{ form }}. I can do this with function-based views but finding it difficult to do with class-based views. Here are the code.
#models.py
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
date_posted = models.DateTimeField(default=timezone.now)
likes = models.ManyToManyField(User, blank=True, related_name='post_likes')
image = models.ImageField(null=False, blank=False, upload_to='post_images')
slug = models.SlugField(unique=True)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
text = models.CharField(max_length=150)
date_commented = models.DateTimeField(auto_now_add=True)
comment_by = models.ForeignKey(User, on_delete=models.CASCADE)
#forms.py
from django import forms
from users.models import Profile
from Post.models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['text', ]
#views.py
from django.views.generic import ListView, DetailView
class PostDetail(DetailView):
model = Post
template_name = 'Post/blog-detail.html'
Hope my question makes sense Thanks.
You can do it, for example:
class PostDetail(DetailView):
model = Post
template_name = 'Post/blog-detail.html'
def get_context_data(self, **kwargs):
context = super(PostDetail, self).get_context_data(**kwargs)
context['comment_form'] = CommentForm()
return context