How to retrieve and assign current user object to a field in Wagtail admin? - django-models

I have a few Django models that I display in the admin using wagtail’s modelAdmin. few of the fields in the models are referencing the user model. Since I’m not creating the form/page and it’s handled by wagtail, how do I pass the current user object to the field when it’s saved? That is, the created and updated by fields should have the current user object assigned to them.
See code snippet below, currently I'm assigning the user manually by querying, instead I'd like to get the current user.
from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
from wagtail.admin.forms import WagtailAdminPageForm
STATUS_CHOICES = (
(1, 'Active'),
(2, 'Inactive')
)
class BasePageForm(WagtailAdminPageForm):
def save(self, commit=True):
auth_user_model = get_user_model()
default_user = auth_user_model.objects.get(username='admin')
page = super().save(commit=False)
if not page.pk:
page.created_by = default_user
page.updated_by = default_user
else:
page.updated_by = default_user
if commit:
page.save()
return page
class BaseModel(models.Model):
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='created%(app_label)s_%(class)s_related'
)
created_at = models.DateTimeField(auto_now_add=True)
updated_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='updated%(app_label)s_%(class)s_related'
)
updated_at = models.DateTimeField(auto_now=True)
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
class Meta:
abstract = True # Set this model as Abstract
base_form_class = BasePageForm

Related

Django Rest Framework: Form field populated with object representation after validation error

After the form is validated the field is populated with object representation from memory.
Form screenshot
I am using MoneyField in my Product model from django-money library.
models.py
class Product(models.Model):
CURRENCY_CHOICES = (
('EUR', 'EUR'),
('USD', 'USD'),
('GBP', 'GBP'),
('PLN', 'PLN')
)
price = MoneyField(max_digits=10, decimal_places=2, blank=False,
currency_choices=CURRENCY_CHOICES)
serializers.py
class ProductSerializer(serializers.ModelSerializer):
price_currency = serializers.ChoiceField(choices=Product.CURRENCY_CHOICES)
class Meta:
model = Product
fields = (
'price','price_currency',
)
views.py
class ProductList(generics.ListCreateAPIView):
serializer_class = ProductSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
queryset = Product.objects.all()
I would really appreciate any suggestions on why this is happening.

How to Implement One to Many in DRF

I am Designing a Model
class Timer(models.Model):
total_time = models.FloatField(default=5)
date_time = models.DateTimeField(auto_now_add=True)
class WatchTiming(models.Model):
user = models.OneToOneField("authentication.User", on_delete=models.CASCADE, primary_key=True)
current_timer = models.ForeignKey(Timer, on_delete=models.CASCADE, related_name="current_timer")
previous_timers = models.ForeignKey(Timer, on_delete=models.CASCADE, related_name="previous_timers")
and serializer for this model is
from rest_framework import serializers
from .models import Timer, WatchTiming
class TimerSerializer(serializers.ModelSerializer):
class Meta:
model = Timer
exclude = ("id",)
class WatchTimingSerializer(serializers.ModelSerializer):
current_timer = TimerSerializer(required=False)
previous_timers = TimerSerializer(many=True, read_only=True)
user = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = WatchTiming
fields = "__all__"
def create(self, validated_data):
watch_timing = WatchTiming.objects.create(user=self.context["request"].user, current_timer=Timer.objects.create())
return watch_timing
WatchTiming is a table that is used to store user watch time
current_timer stores today's timer
when the day expires current_timer values are added in the previous_timer and the current_timer value is replaced with the default
Now My issue is how can I create one to many relationships, I already have written relationships but its not working
I have been stuck on this for 4 consecutive days.
You can use a subserializer, just like you did with your TimerSerializers:
from rest_framework import serializers
from .models import Timer, WatchTiming
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User # authentication.User
fields = (
'id',
'username',
)
class WatchTimingSerializer(serializers.ModelSerializer):
current_timer = TimerSerializer(required=False)
previous_timers = TimerSerializer(read_only=True)
user = serializers.UserSerializer(read_only=True)
class Meta:
model = WatchTiming
fields = '__all__'
def create(self, validated_data):
return WatchTiming.objects.create(
user=self.context['request'].user,
current_timer=Timer.objects.create(),
)
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: The related_name=… parameter [Django-doc]
is the name of the relation in reverse, so from the Timer model to the WatchTiming
model in this case. Therefore it (often) makes not much sense to name it the
same as the forward relation. You thus might want to consider renaming the current_timer relation to watch_timings.
By using SerializerMethodField you can create one to many relationships.
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
class WatchTimingSerializer(serializers.ModelSerializer):
current_timer = TimerSerializer(required=False)
previous_timers = TimerSerializer(many=True, read_only=True)
user = serializers.SerializerMethodField(read_only=True)
class Meta:
model = WatchTiming
fields = "__all__"
def get_user(self, obj):
data = User.objects.filter(id=obj.id)
return UserSerializer(data, many=True).data

How to show this blog django backend by its id in react frontend

models
class Blog(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
serializers
class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = Blog
fields = '__all__'
views
class BlogDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Blog.objects.all()
serializer_class = BlogSerializer
and urls
from django.urls import path
from .views import BlogDetailView
urlpatterns = [
path('blog/<int:pk>/', BlogDetailView.as_view()),
]
I'm trying to make a blog website. How can we show blogs by id in react js
I think you want to get list of blogs ordering by id. So, you can do like this-
views -
class BlogDetailView(generics.ListAPIView):
queryset = Blog.objects.all().order_by('-id') # descending order
serializer_class = BlogSerializer

Django modelformset form is not blank when I return

If the database is empty and I go to my form it looks the way it is supposed to. There is two spots for parent information and two spots for child information. If I fill the form out and submit it I get no errors and I get taken to the thank you page. When I go back to the page with the form there are now four spots for parent information and four spots for child information. Two of the spots for child and parent information are filled out with the data that is now in the database. If you fill in the blank fields new data will get added to the database but if you change any information in the already populated fields it will change the information of the data already in the database. I have even tried manually inputing the data through the admin portal but when I go to the form the information I put in still shows up. It's like the formset is pulling information out of the database. How do I get this form so that when I go back to it after submitting data the form is blank again?
Form after data submission part 1
Form after data submission part 2
models.py
from django.db import models
class Child(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
birthday = models.DateField()
allergies = models.CharField(max_length=30)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Parent(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
child = models.ManyToManyField(Child)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Household(models.Model):
household_name = models.CharField(max_length=30)
parent = models.ManyToManyField(Parent)
def __str__(self):
return self.household_name
forms.py
from django import forms
from .models import Child, Household, Parent
class HouseholdForm(forms.ModelForm):
class Meta:
model = Household
fields = ('household_name',)
class ParentForm(forms.ModelForm):
class Meta:
model = Parent
fields = ('first_name', 'last_name',)
class ChildForm(forms.ModelForm):
class Meta:
model = Child
fields = ('first_name', 'last_name', 'birthday', 'allergies',)
views.py
from django.forms import modelformset_factory
from django.shortcuts import get_object_or_404, render, redirect
from .forms import ChildForm, HouseholdForm, ParentForm
from .models import Child, Parent, Household
def register(request):
ParentFormSet = modelformset_factory(Parent, form=ParentForm, extra=2)
ChildFormSet = modelformset_factory(Child, form=ChildForm, extra=2)
if request.method == "POST":
formset1 = ParentFormSet(request.POST, prefix="parent",)
formset2 = ChildFormSet(request.POST, prefix="child",)
if formset1.is_valid() and formset2.is_valid():
formset1.save()
formset2.save()
return redirect('thanks',)
else:
formset1 = ParentFormSet(prefix="parent",)
formset2 = ChildFormSet(prefix="child",)
return render(request, 'register.html', {'formset1': formset1, 'formset2': formset2,})
def thanks(request):
return render(request, 'thanks.html')

Django: error with "username" in my custom user model - 'UserProfile' object has no attribute 'username'

I'm new with Django and I'm having some problems creating a custom user model. I followed every steps from the django documentation. Here is my model :
class UserProfile(models.Model):
user = models.OneToOneField(User)
comment = models.BooleanField()
score = models.IntegerField(null=True)
profilpic = models.ImageField(upload_to="/profilepics")
bio = models.CharField(max_length=140)
Then I created several users with django-registration. But when I go to the admin and I try to delete a user I created or when I just try to click on the username, I get this error:
AttributeError at /admin/auth/user/3/
'UserProfile' object has no attribute 'username'
Exception Value:
'UserProfile' object has no attribute 'username'
Exception Location: /Users/marc-antoinelacroix/Desktop/Site/sportdub/projet/models.py in __unicode__, line 14
So I think I have to create a "username" in my UserProfile model, and associate it to the username of the django's User, but I have no idea how to do it...
Any help would be welcome.
Thanks!
It seems like you're trying to access
def __unicode__(self):
return self.username
but it has to be
def __unicode__(self):
return self.user
Here's a demo
project/account/models.py
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
homepage = models.URLField(verify_exists=False)
#...
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
project/account/admin.py
from django.contrib import admin
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from account.models import UserProfile
admin.site.unregister(User)
class UserProfileInline(admin.StackedInline):
model = UserProfile
class UserProfileAdmin(UserAdmin):
inlines = [UserProfileInline]
admin.site.register(User, UserProfileAdmin)
project/settings.py
AUTH_PROFILE_MODULE = "account.userprofile"
No, you need to define UserProfile.__unicode__() properly. It needs to get the username from the related User model.

Resources