As this questions says, I am having trouble displaying a ManyToManyField in the django admin page.
The m2m field that I'm having trouble displaying is comics in the Gig model.
Here is the code for my project:
#models.py file
class Host(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='host')
name = models.CharField("Venue Name", max_length=200)
slug = models.SlugField(allow_unicode=True, blank=True, null=True)
description = models.TextField("Brief Venue Description - [50 Characters Max]", max_length=50, blank=True)
profile_pic = models.ImageField("Profile Picture", upload_to='host/profile_pics',blank=True)
class Gig(models.Model):
host = models.ForeignKey(Host, on_delete=models.CASCADE, blank=True, related_name='host_gigs')
title = models.CharField("Gig Title",max_length=50, null=True)
date_time = models.DateTimeField("Date/Time of Gig", null=True, blank=True)
description = models.TextField("Describe this gig", max_length=150, blank=True)
instructions = models.CharField('Instructions for accepted comics', max_length=200, blank=True, null=True)
comics = models.ManyToManyField("comic.Comic", through='comic.ComicGig',related_name='gig_comics', default=" ")
#in separate app
#models.py
class Comic(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, related_name='comic')
dob = models.DateField("Date of Birth", null=True, blank=True)
mobile = PhoneNumberField(null=True, blank=True)
slug = models.SlugField(allow_unicode=True, blank=True, null=True)
class ComicGig(models.Model):
thegig = models.ForeignKey('host.Gig', on_delete=models.CASCADE, default="", related_name='comic_gig')
comic = models.ForeignKey(Comic, on_delete=models.CASCADE, default="")
approved_comic = models.BooleanField(default=False, null=True)
def approve(self):
self.approved_comic = True
self.save()
Here is my Host admin.py file:
class AuthorAdmin(admin.ModelAdmin):
list_display = ('host', 'title',)
filter_horizontal = ('comics',)
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "comics":
kwargs["queryset"] = Gig.objects.filter(comic_gig__approved_comic=True)
return super().formfield_for_manytomany(db_field, request, **kwargs)
admin.site.register(Host)
admin.site.register(Gig, AuthorAdmin)
Here is a picture of my Host model in the admin
Here is a picture of my ComicGig model in the admin
Related
I have a create view (Loan_assetCreateView(generic.CreateView)) where I save if an asset is going to be loaned and when it will be returened in a model called Loan_asset(models.Model). Then I have the asset in a diffrent model Asset(model.Model). I would like to once I have saved my data in my Loan_assetCreateView(generic.CreateView) that is set the value in Asset.is_loaned to True. How can I do that?
My models.py:
class Asset(models.Model):
# Relationships
room = models.ForeignKey("asset_app.Room", on_delete=models.SET_NULL, blank=True, null=True)
model_hardware = models.ForeignKey("asset_app.Model_hardware", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
name = models.CharField(max_length=30)
serial = models.CharField(max_length=30, unique=True, blank=True, null=True, default=None)
mac_address = models.CharField(max_length=30, null=True, blank=True)
purchased_date = models.DateField(null=True, blank=True)
may_be_loaned = models.BooleanField(default=False, blank=True, null=True)
is_loaned = models.BooleanField(default=False, blank=True, null=True)
missing = models.BooleanField(default=False, blank=True, null=True)
notes = HTMLField(default="")
ip = models.CharField(max_length=90, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Loan_asset(models.Model):
# Relationships
asset = models.ForeignKey("asset_app.Asset", on_delete=models.SET_NULL, blank=True, null=True)
loaner_type = models.ForeignKey("asset_app.Loaner_type", on_delete=models.SET_NULL, blank=True, null=True)
location = models.ForeignKey("asset_app.Locations", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
loaner_name = models.CharField(max_length=60)
loaner_address = models.TextField(max_length=100, null=True, blank=True)
loaner_telephone_number = models.CharField(max_length=30)
loaner_email = models.EmailField()
loaner_quicklink = models.URLField(null=True, blank=True)
loan_date = models.DateField()
return_date = models.DateField()
notes = HTMLField(default="")
returned = models.BooleanField(default=False, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Meta:
pass
def __str__(self):
return str(self.loaner_name)
def get_absolute_url(self):
return reverse("asset_app_loan_asset_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_loan_asset_update", args=(self.pk,))
my urls.py
`path("asset_app/loan_asset/create/", views.Loan_assetCreateView.as_view(), name="asset_app_loan_asset_create")`,
my views.py
class Loan_assetCreateView(generic.CreateView):
model = models.Loan_asset
form_class = forms.Loan_assetForm
Here are some options:
override form_valid method that's being called in post method implementation, so that after form will be validated (model instance saved), you'll be able to set the flag through foreign key/by creating Asset instance:
...
def form_valid(self, form):
self.object = form.save()
if self.object.asset:
self.object.asset.is_loaned = True
else:
self.object.asset = Asset.objects.create(is_loaned=True)
return HttpResponseRedirect(self.get_success_url())
use Django signals:
#receiver(post_save, sender=Loan_asset)
def create_transaction(sender, instance, created, **kwargs):
if created:
Asset.objects.create(is_loaned=True)
You can override the post method in your Loan_assetCreateView.
class Loan_assetCreateView(generic.CreateView):
model = models.Loan_asset
form_class = forms.Loan_assetForm
def post(request, *args, **kwargs):
response = super().post(request, *args. **kwargs)
# Do your thing
return response
I am making a app for one kindergarten in my city. I have kids model and payment model.
For updating kid I am using class based view generic UpdateView and for creating a payment i am using form and function view. I have not problems with payment form when I am using a different template but when I try to put it on the same template, payment form is not showing up and it's not working. Is it possible to have payment form on same template as UpdateView class ? I am using UpdateView class as profile page and I would like to have payment form on the same page. Please help. Thanks
models:
class Kids(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
city_birthday = models.CharField(max_length=100, blank=True, null=True)
custom_id = models.CharField(max_length=100 ,blank=True, null=True)
gender = models.CharField(max_length=100, choices=gender_choices, null=True, blank=True)
address = models.CharField(max_length=250, null=True, blank=True)
contact_phone = models.CharField(max_length=100, blank=True, null=True)
family_size = models.IntegerField(null=True, blank=True)
living_with = models.CharField(max_length=100, choices=living_choices, null=True, blank=True)
number_of_preschool_kids_in_family = models.IntegerField(null=True, blank=True)
kid_already_been_in_kindergarten = models.CharField(max_length=100, choices=preschool_choices,
null=True, blank=True ,default=False)
father_name = models.CharField(max_length=100, blank=True, null=True)
father_education_level = models.CharField(max_length=200, blank=True, null=True)
father_company = models.CharField(max_length=200, blank=True, null=True)
mother_name = models.CharField(max_length=100, blank=True, null=True)
mother_education_level = models.CharField(max_length=200, blank=True, null=True)
mother_company = models.CharField(max_length=200, blank=True, null=True)
parent_notes = models.CharField(max_length=500, blank=True, null=True)
program_choice = models.CharField(max_length=100, choices=kindergarten_program_choice, null=True,
blank=True)
def __str__(self):
return self.name
class Meta:
ordering = ['name']
class Payment(models.Model):
user = models.ForeignKey(Kids, on_delete=models.CASCADE, blank=True, null=True)
bank_paper_id = models.IntegerField(null=True, blank=True)
payment_date = models.CharField(max_length=100, null=True, blank=True)
paid = models.FloatField(null=True, blank=True)
need_to_pay = models.FloatField(null=True, blank=True)
notes = models.CharField(max_length=500, blank=True, null=True)
def __str__(self):
return self.user.name
views:
class UpdateKidView(UpdateView):
model = Kids
fields = '__all__'
template_name = 'vrtic/update_kid.html'
success_url = reverse_lazy('vrtic:kids')
def create_payment(request, pk):
kid = Kids.objects.get(id=pk)
payment_form = PaymentForm()
if request.method == 'POST':
payment_form = PaymentForm(request.POST)
if payment_form.is_valid():
payment = payment_form.save(commit=False)
payment.user = kid
payment_form.save()
return redirect('vrtic:kids')
context = {
'payment_form': payment_form,
'kid': kid
}
return render(request, 'vrtic/update_kid.html', context)
form:
class PaymentForm(forms.ModelForm):
class Meta:
model = Payment
fields = '__all__'
class UpdateKidView(UpdateView):
model = Kids
form_class = KidsForm
second_form_class = PaymentForm
template_name = 'vrtic/update_kid.html'
success_url = reverse_lazy('vrtic:kids')
def get_context_data(self, **kwargs):
context = super(UpdateKidView, self).get_context_data(**kwargs)
context['form'] = self.form_class(instance=self.get_object())
context['second_form'] = self.second_form_class()
return context
def post(self, request, **kwargs):
kids_form = self.form_class(request.POST, request.FILES, instance=self.get_object())
if kids_form.is_valid():
kid = kids_form.save()
payment_form = self.second_form_class(request.POST)
...
Not the happiest solution, but u got the idea, if need more help contact me to explain on Serbian, not sure how are the rules here for languages : )
In a form I have a drop down of usernames, this is referenced in the 'taken_by' field. I would like to display first_name and last_name, this is achieved through the __str__ but I can't seem to get it to function, the list of usernames are presented but not the firstname. Suggestions welcome.
from django.contrib.auth.models import User
from django.conf import settings
class Sample(models.Model):
sample_id = models.AutoField(primary_key=True)
area_easting = models.IntegerField(choices = EASTING_CHOICES)
area_northing = models.IntegerField(choices = NORTHING_CHOICES)
context_number = models.IntegerField()
sample_number = models.IntegerField()
material_type = models.CharField(max_length=200, default='', blank=True, null=True, choices = MATERIALS)
weight = models.DecimalField(max_digits=6, decimal_places=2)
description = models.CharField(max_length=500, default='', blank=True, null=True)
recovery_method = models.CharField(max_length=200, default='', blank=True, null=True, choices = RECOVERY_METHODS)
taken_by = models.ForeignKey(settings.AUTH_USER_MODEL, db_column='taken_by', on_delete = models.PROTECT)
comments = models.CharField(max_length=1000, default='', blank=True, null=True)
def __str__(self):
return self.taken_by.first_name
# return str(self.sample_id)
# return str(self.firstname)+ '-' +str(self.lastname)
# return u'%s %s' % (self.first_name, self.last_name)
Form setup as requested
class BotanySampleFilterForm(forms.ModelForm):
class Meta:
model = Sample
fields = (
# 'botany_id',
'sample_id',
'area_easting',
'area_northing',
'context_number',
'sample_number',
'material_type',
'weight',
'description',
'recovery_method',
'taken_by',
'comments'
)
Following are the models of my app:
class Store(models.Model):
store_owner = models.ForeignKey(User, null=False, verbose_name='User')
store_name = models.CharField(max_length=200, null=False,
verbose_name='Store name')
store_address_line_1 = models.CharField(max_length=200, null=False,
verbose_name='Address line 1')
store_address_line_2 = models.CharField(max_length=200, null=False,
verbose_name='Address line 2')
store_city = models.CharField(max_length=200, null=False,
verbose_name='City')
store_state = models.CharField(max_length=200, null=False,
verbose_name='State')
store_zip_code = models.CharField(max_length=200, null=False,
verbose_name='Zip/Pin Code')
store_country = models.CharField(max_length=200, null=False,
verbose_name='Country')
store_phone = models.CharField(max_length=12, verbose_name='Phone')
store_email = models.EmailField(verbose_name='Email')
store_website = models.URLField(verbose_name='Website')
class StoreDepartment(models.Model):
store = models.ForeignKey(Store, verbose_name='Store')
department_name = models.CharField(max_length=200, null=False,
verbose_name='Department name')
department_description = models.TextField(max_length=250, null=False,
verbose_name='Description')
+++++++++
I am using only the dfault Admin provided by django framwork.
I have 2 users, For both users I have created Stores.
But when I try to create StoreDepartment, I see the list of all the stores in the Select box created for "Store" foreign-key field in StoreDepartment model.
How to customize the default form so that user can see only the Stores created by them in the selectbox.
I used the following formfield_for_foreignkey in Model admin and now its working for me. User can see only the stores owned by him.
class StoreDepartmentAdmin(admin.ModelAdmin):
list_display = ['department_name', 'store']
ordering = ['id']
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "store":
kwargs["queryset"] =Store.objects.filter(store_owner=request.user)
return super(StoreDepartmentAdmin,self).formfield_for_foreignkey(db_field, request, **kwargs)
I installed django profiles/registration and everything seems to be fine. When a user registers their profile is created also. Now what i want to do is query another Model which is Company based on the user id of User. I dont want to change django-profiles view but add the extra field on urls to match and query Company model. When i hardcode the url (ex:put the id number of the userprofile like so userprofile=1, it works.). So when a user is logged in and goes to profile detail page Company assigned to them is queried based on their user.id.
class UserProfile(models.Model):
user = models.OneToOneField(User)
#email = models.CharField(max_length=200, blank=True, null=True)
# Other fields here
#company = models.ForeignKey(Company,blank=True,null=True)
#office = models.CharField(max_length=200, blank=True, null=True)
def __unicode__(self):
return self.user.username
class Company(models.Model):
userprofile = models.ForeignKey(UserProfile, null=True, blank=True)
comp_name = models.CharField(max_length=200,blank=True,null=True)
comp_address = models.CharField(max_length=200,blank=True, null=True)
comp_email = models.CharField(max_length=200,blank=True, null=True)
comp_zip = models.IntegerField(blank=True, null=True)
comp_phone = models.IntegerField(blank=True, null=True)
comp_city = models.CharField(max_length=200,blank=True, null=True)
#comp_state = models.USStateField(blank=True, null=True
comp_state = models.CharField(blank=True, max_length=2)
compwebsite = models.URLField(max_length=200, blank=True, null=True)
twitterurl = models.URLField(max_length=200, blank=True, null=True)
facebookurl = models.URLField(max_length=200, blank=True, null=True)
def __unicode__(self):
return self.comp_name
url(r'^profiles/(?P<username>\w+)/$', 'profiles.views.profile_detail', {'extra_context':{'queryset':Company.objects.filter(userprofile=request.user.id)}},),
You might want to call it from inside a view
from *** import profile_detail
def my_view(request, username):
extra_context = {}
return profile_detail(request, queryset=Company.objects.filter(userprofile=request.user.id),
template_name="my_template.html",
paginate_by=20,
extra_context=extra_context)