Django Model: ForeignKey and Relations - python

I have 2 models:
class Post(models.Model):
pass
class Vote(models.Model):
post = models.ForeignKey(Post)
user = models.ForeignKey(django.contrib.auth.models.User)
I want to allow logged User to make a vote on Post's Admin site. I think about 2 solution as below:
Add 'voted' field to Post model.
Customize Post's Admin forms by add a Button control and implement do_vote() function in Post model to call when the Button is clicked.
Do you have any other solutions?
Additionally, I don't know how to implement 2 above solutions.
Could you give me some lines of code?

On your PostAdmin class you can add an action:
class PostAdmin(admin.ModelAdmin):
...
actions = [vote_on_post,]
and then you can implement the vote_on_post method based on this documentation, should be something like this:
#admin.action(description='Vote on action')
def vote_on_post(modeladmin, request, queryset):
user = request.user
for post in queryset:
Vote.objects.create(user=user,post=post)
You probably want to add logic to prevent multiple votes from the same user on the same post, etc.

Related

How to add check on admin side actions in django?

Here i'm using django latest verion which is 3.1.4 and I just want to add condition in django admin side. I just wanted to return some text in terminal if i update my model from admin panel.
In my case
user submit kyc form
admin person approved that form
user will get notification on approval. (Right now I just want to print some message when admin update his kyc by updating his kyc form by updated approved boolean field.
In short Just wanted to show message when admin updates any model in django admin side.
admin.py
class KycAdmin(admin.ModelAdmin):
list_display = ['__str__','owner']
class Meta:
model = KycModel
def post(self,request):
response = "i'm updated"
print(vu)
return vu
admin.site.register(KycModel,KycAdmin)
If more detail is require then you can just tell me in a comments.
Have you tried overriding the save method in models.
Whenever you save an object, it will hit the save method. You can print whatever you want to over there
class SomeModel(models.Model):
... some fields for eg. name
def save(self, *args, **kwargs):
print(self.name)
super().save(*args, **kwargs)
This is the simplest way to achieve it. You can also override save in admin.

Many to many relation django in post to signs to post

So I want to make a sign-ups model for my app. This model needs to have 2 fields, a post field and a users field. Both fields are a many 2 many relation with the User model and Post model. But I don't know how to achieve that.
Here is what I have:
this is the models.py
class Post(models.Model):
title = CharField(max_length=250)
...
def __str__(self):
return self.title
class SignUpPost(models.Model):
post = models.OneToOneField(Post,on_delete=models.CASCADE,primary_key=True,)
users = models.ManyToManyField(User)
so many users can be signed up in a post. I have no idea how to do the forms.py and the views.py to store the data.
I want to have in the post detail view a "sign up" button, and when clicked, fill the sign up form with the data of the post and user that clicked the button. And so, the database will have in the post field the post_id and in the users field the users_id of every user that signed up to the post.
thanks in advance

not saving custom fields to django-allauth - no luck from previous posts

I am trying to create custom fields for users to enter on signup with django-allauth. I have referred to several posts about this, but I am not able to get my custom form to save to my database. I do get a combined form on my signup.html page with username, password1 and 2, email and my extra fields of city and school, but I am not able to save the extra fields to the database. I have run syncdb and can see my User Profile table in the admin area.
This advice is the closest I have come to the answer but I do not understand how to implement it: "You can't use UserProfileForm to the allauth.SIGNUP_FORM_CLASS. You need to extend it from SignUpForm and write a save method which will accept the newly created user as the only parameter," from this post:
Custom registration form for use with django-allauth
I have also attempted to integrate advice on this form these posts:
Django Allauth not saving custom form
How to customize user profile when using django-allauth
This is my code:
Models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
# A required line - links a UserProfile to User.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
school = models.CharField(max_length=128)
city = models.CharField(max_length=128)
def __unicode__(self):
return self.user.username
Forms.py
from django import forms
from django.contrib.auth.models import User
from myapp.models import UserProfile
from django.forms.widgets import HiddenInput
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('city', 'school')
def signup(self, request, user):
user=User.objects.get(email=request.email)
city=request.POST.get('city','')
school=request.POST.get('school','')
userprofile_obj = UserProfile(user=user,city=city,school=school)
userprofile_obj.save()
Settings.py
ACCOUNT_SIGNUP_FORM_CLASS = 'myapp.forms.UserProfileForm'
My template is the basic Signup.html from the django-allauth templates and I do not have a view made for this, although I attempted to make one from the tangowithdjango user authentication section register view, and this gave similar behavior (not saving to the database).
Thanks,
Kelly
Not sure if this is still an active question/issue for the original poster: if so, and for anyone else who comes across this, a few things to correct to at least move in the right direction:
I don't see an __init__() method that calls the superclass? E.g.:
def __init__(self, *args, **kwargs):
super(SignupForm, self).__init__(*args, **kwargs)
use the user parameter to the signup method. It should be populated; don't reload it.
Ensure the two objects are linking correctly (I didn't use Django to build my profile table so YMMV but I set user.profile = Profile(...); then execute user.profile.save() at the end of my signup() method.
get the values to place into the profile from the form cleaned_data (e.g. self.cleaned_data['city'] not the POST.
Then start debugging: is your signup() method firing? What does it get? What happens when you execute the profile.save() method?

Displaying ForeignKey data in Django admin change/add page

I'm trying to get an attribute of a model to show up in the Django admin change/add page of another model. Here are my models:
class Download(model.Model):
task = models.ForeignKey('Task')
class Task(model.Model):
added_at = models.DateTimeField(...)
Can't switch the foreignkey around, so I can't use Inlines, and of course fields = ('task__added_at',) doesn't work here either.
What's the standard approach to something like this? (or am I stretching the Admin too far?)
I'm already using a custom template, so if that's the answer that can be done. However, I'd prefer to do this at the admin level.
If you don't need to edit it, you can display it as a readonly field:
class DownloadAdmin(admin.ModelAdmin):
readonly_fields = ('task_added_at',)
def task_added_at(self, obj):
return obj.task.added_at

django-admin - how to modify ModelAdmin to create multiple objects at once?

let's assume that I have very basic model
class Message(models.Model):
msg = models.CharField(max_length=30)
this model is registered with admin module:
class MessageAdmin(admin.ModelAdmin):
pass
admin.site.register(Message, MessageAdmin)
Currently when I go into the admin interface, after clicking "Add message" I have only one form where I can enter the msg.
I would like to have multiple forms (formset perhaps) on the "Add page" so I can create multiple messages at once. It's really annoying having to click "Save and add another" every single time.
Ideally I would like to achieve something like InlineModelAdmin but it turns out that you can use it only for the models that are related to the object which is edited.
What would you recommend to use to resolve this problem?
This may not be exactly what you are looking for, but if you want to create multiple objects at the same time you could to somehthing like this:
#In /forms.py
MessageAdminForm(forms.ModelForm):
msg = CharField(max_length=30)
count = IntegerField()
#In /admin.py
from app.admin import MessageAdminForm
MessageAdmin(admin.ModelAdmin):
form = MessageAdminForm
fieldsets = (
(None, {
'fields' : ('msg','count')
}),)
def save_model(self, request, obj, form, change):
obj.msg = form.cleaned_data['msg']
obj.save()
for messages in range(form.cleaned_data['count']):
message = Message(msg=form.cleaned_data['msg'])
message.save()
Basicly what you are doing is creating a custom form for your admin template, which ask the user how many times the object shall be created. The logic is than interpreted in the save_model method.
As a workaround, Since, It is likely that you have a FK to User, so you could define an InlineModel on the User model.
Otherwise, the easiest approach may be to create a custom admin view since, there isn't a generic admin view that displays and saves formsets.
This is easy if you are using an Inline. Then you could use extra = 10 or however many extra formsets you want. There doesn't seem to be an equivalent for the ModelAdmin.
Of course in your messages model you would need to create a ForeignKey to some sort of message grouping model as another layer of function and to get the multi-formset layout that you are looking for.
For example:
models.py:
class Group(models.Model):
name = models.CharField(max_length=30)
class Message(models.Model):
msg = models.CharField(max_length=30)
grp = models.ForeignKey(Group)
admin.py:
class MessageInline(admin.TabularInline):
model = Message
extra = 10
class GroupAdmin(admin.ModelAdmin):
inlines = [MessageInline]
admin.site.register(Group, GroupAdmin)
This would give you what you want in the Admin view and create grouping (even if you only allow for one group) and the only extra field would be the name in the group model. I am not even sure you would need that. Also I am sure the value for extra could be generated dynamically for an arbitrary value.
I hope this helps!

Categories