Problem relating to driving licences. A licence has a named person who is assiged multiple categories of driving skills. Each category of driving skill has a single renewal date and possible multiple related restrictions
Name Lic Cat Renewal date Restrictions
Tommy AM 12/05/15 44.01, 101, 999
Tommy E+B 14/12/16
Tommy C 18/04/18 101
TG E+C 14/12/16 90, 101, 999,
TG B 18/04/18 105
models.py
class Employee(models.Model):
name = models.CharField(max_length=75)
class DrivingLicenceCategory(models.Model):
name = models.CharField(max_length=11)
class IssuingBody(models.Model):
name = models.CharField(max_length=75)
class DrivingLicence(models.Model):
employee_id = models.ForeignKey(Employee)
driver_number = models.CharField(max_length=49)
permit_number = models.CharField(max_length=49)
issuing_body = models.ForeignKey(IssuingBody)
expiry_date = models.DateField()
class DrivingLicenceRestrictions(models.Model):
name = models.CharField(max_length=21)
description = models.CharField(max_length=1024, blank=True, null=True)
class DrivingLicenceCategoryRestrictions(models.Model):
licence_category = models.ForeignKey(DrivingLicenceCategory)
licence_restriction = models.ForeignKey(DrivingLicenceRestrictions)
expiry_date = models.DateField()
class DrivingLicenceDetail(models.Model):
driving_licence = models.ForeignKey(DrivingLicence)
category_restriction = models.ManyToManyField(DrivingLicenceCategoryRestrictions)
admin.py
from django.contrib import admin
from drvlic.models import *
class DrvLicIssuingBodyAdmin(admin.ModelAdmin):
search_fields = ('^name', )
class DrvLicCategoryAdmin(admin.ModelAdmin):
search_fields = ('^name',)
class DrvLicRestrictionsAdmin(admin.ModelAdmin):
search_fields = ('^name', )
list_display = ('id', 'name', 'description',)
class DrvLicLicenceAdmin(admin.ModelAdmin):
search_fields = ('^employee',)
class DrvLicCategoryRestrictionsAdmin(admin.ModelAdmin):
search_fields = ('^employee',)
filter_horizontal = ('licence_category', 'licence_restriction')
admin.site.register(DrvLicIssuingBody, DrvLicIssuingBodyAdmin)
admin.site.register(DrvLicCategory, DrvLicCategoryAdmin)
admin.site.register(DrvLicRestrictions, DrvLicRestrictionsAdmin)
admin.site.register(DrvLicLicence, DrvLicLicenceAdmin)
admin.site.register(DrvLicCategoryRestrictions, DrvLicCategoryRestrictionsAdmin)
Is my model correct to produce the table above in Django Admin or should the model be different? How is admin.py set up to allow access and enter the data?
Django is telling me that 'DrvLicCategoryRestrictionsAdmin.filter_horizontal[0]' must be a ManyToManyField'. This is irrevelent if the models.py are constructed incorrectly, I think.
You don't need the '^' for the search field. Just search_fields = 'name' should suffice.
To display a ManyToManyField, you need to loop through all associated objects. But, even before that point, I think you need to restructure your models to have one 'all encompassing' model that holds that table you are trying to produce. So, something like:
models.py
class License(models.Model):
employee = models.ForeignKey(Employee)
category = models.ManyToMany(DrivingLicenceCategory)
restriction = models.ManyToMany(DrivingLicenceRestrictions)
expiry_date = models.DateField()
def get_categories(self):
return ",<br>".join([a.name for a in self.category.all()])
def get_restrictions(self):
return ",<br>".join([a.name for a in self.restriction.all()])
admin.py
class LicenseAdmin(admin.ModelAdmin):
list_display = ('employee', 'get_categories', 'get_restrictions', 'expirary_date')
Related
So I have a product Model which say looks like this :
class ProductModel(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=6, decimal_places=2, null=True)
and I also have a cart model which looks like this :
class CartModel(models.Model):
customer = models.ForeignKey(User, on_delete= models.CASCADE, related_name="cart")
products = models.ManyToManyField(ProductModel)
the thing is I want to add a quantity field to the product so the user can add multiple products from the same product in the cart But I only want it when the product is in a cart (I don't want to add it in the ProductModel) Instead I want to add it to the product fields in the many to many relationship. I've done a bit of research and most of the answers aren't clear enough on how I should be doing this.
You can create new fields in the intermediate relation table between Products and Cart. You have to define a new class for this intermediate table and to use it with the through attribute of the M2M field.
from django.db import models
from django.contrib.auth.models import User
class ProductModel(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=6, decimal_places=2, null=True)
def __str__(self):
return self.name
class Meta:
verbose_name = "Product"
class CartModel(models.Model):
customer = models.ForeignKey(User, on_delete=models.CASCADE, related_name="cart")
products = models.ManyToManyField(ProductModel, through='ProductCart')
def __str__(self):
return "Cart nÂș {} - {}".format(self.pk, self.customer)
class Meta:
verbose_name = "Cart"
class ProductCart(models.Model):
product = models.ForeignKey(ProductModel, on_delete=models.CASCADE)
cart = models.ForeignKey(CartModel, on_delete=models.CASCADE)
quantity = models.IntegerField()
def __str__(self):
return ' '
One way for displaying it in the admin can be to use TabularInline for the products of the cart:
from django.contrib import admin
from .models import CartModel
class ProductsInline(admin.TabularInline):
model = CartModel.products.through
extra = 0
exclude = ()
verbose_name = 'Product'
class CartAdmin(admin.ModelAdmin):
list_display = ('customer',)
list_filter = ('customer',)
inlines = [
ProductsInline,
]
admin.site.register(CartModel, CartAdmin)
models.py
class Product(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(decimal_places=5,max_digits= 1500)
summary = models.TextField()
featured = models.BooleanField()
def __str__(self):
return self.title
# return f'product title:{self.title}-product price:{self.price}'workok
class Meta:
ordering = ('-price',)
class Opinion(models.Model):
name = models.CharField(max_length=20)
email = models.EmailField(max_length=20)
body = models.TextField()
opinion_date = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='opinion_set')
def __str__(self):
return f'({self.name}) add opinion about ({self.product})'
forms.py:
from django.forms import ModelForm
from .models import Product #space after from keyword
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
invalid in code line :
fields = ['name','email','body','product'] #---- NOT WORK !!!
, but if i change above code to :
fields = "__all__" # ----it is WORKing ok without any problem !!
question : what is the error? I am not need all the fields in the Product model (like active boolean field), I need only 'name','email','body','product' fields .
According to the error and the code you provided the main problem is that you made a mistake in chosing model in serializer:
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
Serializer name is OpinionModelForm and listed fields belong to Opinion so I guess you actually wanted to serialize Opinion and no Product as you defined at this line:
model = Product
Simply change it to:
model = Opinion
I have following models:
from django.db import models
class City(models.Model):
name = models.CharField(max_length=30)
last_update = models.DateTimeField(null=True)
class BusStop(models.Model):
city = models.ForeignKey(City, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True, default='')
Now using Django Rest Framework, I would like to create serializer that will return City details along with the list of all BusStops in the city - but I want the list to be only strings with BusStop names, like this:
{
"id": 1
"name": "City"
"last_update": "2019-09-19T22:13:54.851363Z"
"bus_stops": [
"stop1",
"stop2",
"stop3"
]
}
What I've tried so far is following serializers:
from rest_framework import serializers
class BusStopSerializer(serializers.ModelSerializer):
class Meta:
model = BusStop
fields = ('name', )
class CityDetailsSerializer(serializers.ModelSerializer):
busstop_set = BusStopSerializer(many=True)
class Meta:
model = City
fields = ('id', 'name', 'last_update', 'busstop_set')
But this creates list of objects with 'name' in them. So, how can I create a list with only BusStop names (as strings) in it?
Instead of the extra BusStopSerializer you could use a StringRelatedField:
# models.py
class BusStop(models.Model):
city = models.ForeignKey(City, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True, default='')
def __str__(self):
return self.name
# serializers.py
class CityDetailsSerializer(serializers.ModelSerializer):
bus_stops = StringRelatedField(many=True)
class Meta:
model = City
fields = ('id', 'name', 'last_update', 'bus_stops')
StringRelatedField, as recommended by wfehr, will only work as long as the __str__ method of BusStop only returns the name. An alternative is to use SlugRelatedField which allows you to specify a particular field from the related model, and has no dependency on __str__.
bus_stops = SlugRelatedField(many=True, slug_field='name')
I am creating form for users to input information too. I then want to save that information to a database and be able to extract information.
I am having difficulty however when I try to create a drop down list and multiple selection list. For example say I define a model as in my models.py file as such:
gi_category = models.CharField(max_length=4, choices=GI_NOGI)
Where I have GI_NOGI specified as
GI_NOGI = (('GI','GI'),('NOGI','NO-GI'))
My forms.py looks something like this
class RegisterForm(forms.ModelForm):
weightclass = forms.ChoiceField(choices=WEIGHTCLASS, required=True,label='Weight Class')
gi_category = forms.MultipleChoiceField(choices=GI_NOGI, label='Contest You Intend to Enter', widget=forms.CheckboxSelectMultiple(), required=True)
class Meta:
model = Register
fields = ['name', 'age', 'birthdate', 'address', 'city', 'state', 'zip',
'phone', 'email']
labels = {'name':'Name', 'age':'Age on April 21', 'birthdate':'Birth date',
'address':'Address', 'city':'City', 'state':'State', 'zip':'Zip',
'phone':'Phone', 'email':'Email'}
widgets = {
'birthdate':forms.TextInput(attrs={'placeholder': 'MM/DD/YYYY'}),
'phone':forms.TextInput(attrs={'placeholder': '(###)-###-####'})}
Now I believe I am overwriting the gi_category and weightclass from models somehow because I cant access their respective values in the database. I don't know how to create a SelectMultiple any other way than I had I did(If this is problem any insight would be great.
I am wondering what I am doing wrong?
Also on a related note I want to have a database value for gi_category in which it can either have values of 'NO-GI' or/and 'GI'
I am saving the form values using this views.py
WEIGHTCLASS = (
('MFYW','Men Fly Weight(129 lbs. & Under)'),
('MBW','Men Bantan Weight(130 lbs. to 139.9 lbs)'),
('MFEW','Men Feather Weight(140 lbs. to 149.9 lbs.)')
)
GI_NOGI = (('GI','GI'),
('NOGI','NO-GI')
)
class Register(models.Model):
"""register some text"""
name = models.CharField(max_length=200)
age = models.CharField(max_length=3)
email = models.EmailField(max_length=200)
birthdate = models.DateField()
address = models.CharField(max_length=200)
city = models.CharField(max_length=200)
state = models.CharField(max_length=200)
zip = models.CharField(max_length=5)
phone = models.CharField(max_length=14)
weightclass = models.CharField(max_length=4, choices=WEIGHTCLASS)
gi_category = models.CharField(max_length=4, choices=GI_NOGI)
def __str__(self):
"""Return a string represenation of the model."""
return self.weightclass
Thanks
Disclaimer: I am learning django as I apply it to a database / PHP app i inherited. The database is a bit of a mess, with no foreign key constrains, and inconsistent naming. I do not want to touch or redo anything on the database because I don't want to mes with the legacy application at all.
Stack: Python 2.7. Django 1.5, Django Rest Framework
The problem is that I have a relationship where there is an Idea that has multiple Tickers. The tickers table has the foreign key to the ideas (teaser_id) so that we have something like
**Tickers**
id teaser_id
1 1
2 1
3 1
4 2
4 2
**Ideas**
id
1
2
I had django generate the model from the database, but without the FK Constraints it didn't generate all the relationships properly. So here is haw the models are configured:
class Tickers(models.Model):
id = models.IntegerField(primary_key=True)
# I changed to this
teaser_id = models.ForeignKey(Idea)
# From
# teaser_id = models.IntegerField(null=True, blank=True)
ticker = models.CharField(max_length=135L, blank=True)
date_added = models.CharField(max_length=135L, blank=True)
class Meta:
db_table = 'teaser_tickers'
class Idea(models.Model):
id = models.IntegerField(primary_key=True)
industry_id = models.IntegerField()
post_type = models.CharField(max_length=45L)
class Meta:
db_table = 'idea'
Here are my serializers
class TickerSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = myModels.Tickers
fields = (
'id'
,'teaser_id'
,'ticker'
)
class IdeaSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False, read_only=True)
ticker = TickerSerializer(many=True, read_only=True, )
teaser = myFields.TeaserField(teaser_length=200, original_field='content')
class Meta:
model = myModels.Idea
fields = (
'id'
, 'title'
, 'date_added'
, 'user'
, 'teaser'
, 'ticker'
)
I want the Ideas Resource to return the tickers as a child node set.
The REST request is for the Idea where the tickers is a child element. So I am getting an exception that ticker isn't defined in idea. Fine get that - but I am just guessing on how to set this up at this point - I am sludging through documentation and source - but was hoping someone could help me out.
THank you
As akaphenom said you have to use the related_name in your serializer, but since you don't specify any in your models you must use the default, in this case teaser_set and your IdeaSerializer must be:
class IdeaSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False, read_only=True)
tickers = ReverseTickerSerializer(many=True, read_only=True)
teaser_set = myFields.TeaserField(teaser_length=200, original_field='content')
class Meta:
model = myModels.Idea
fields = (
'id',
'title',
'date_added',
'user',
'teaser_set',
'tickers',
)
SO the solution for the reverse lookup is specifying the model correctly, and namely the related_name which is the field that is created in the foreign model to perform the reverse look up. Now I specified a custom serializer to limit to the content I am interested in - but that piece is optional.
class Tickers(models.Model):
id = models.IntegerField(primary_key=True)
# I changed to this
teaser_id = models.ForeignKey(Idea, related_name='tickers')
# From
# teaser_id = models.IntegerField(null=True, blank=True)
ticker = models.CharField(max_length=135L, blank=True)
date_added = models.CharField(max_length=135L, blank=True)
class Meta:
db_table = 'teaser_tickers'
class Idea(models.Model):
id = models.IntegerField(primary_key=True)
industry_id = models.IntegerField()
post_type = models.CharField(max_length=45L)
class Meta:
db_table = 'idea'
Here are my serializers
class ReverseTickerSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = myModels.Tickers
fields = (
'id'
,'ticker'
)
class IdeaSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False, read_only=True)
tickers = ReverseTickerSerializer(many=True, read_only=True)
teaser = myFields.TeaserField(teaser_length=200, original_field='content')
class Meta:
model = myModels.Idea
fields = (
'id'
, 'title'
, 'date_added'
, 'user'
, 'teaser'
, 'tickers'
)