I'm starting to build a REST API with Django for study purposes and I have encountered an obstacle.
I have the following model:
class ExampleModel(models.Model):
name = models.CharField(max_length = 36)
class_type = models.CharField(max_length = 10)
timestamp = models.PositiveIntegerField()
last_timestamp = models.PositiveIntegerField()
and a serializer:
class ExampleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ExampleModel
fields = '__all__'
read_only_fields = ['timestamp', 'last_timestamp']
def create(self, validated_data, **kwargs):
validated_data['timestamp'] = int(datetime.timestamp(datetime.now()))
#validated_data['last_timestamp'] = ...
return ExampleModel.objects.create(**validated_data)
I would like to fill the last_timestamp field with the timestamp value of the last entry that matches with the class_type of the current one.
Using the psycopg2 lib a simple solution could be:
last_entry_query = 'SELECT max(id) FROM example_table WHERE class_type = %s' % current_type
get_timestamp = 'SELECT timestamp FROM example_table WHERE id = (%s)' % last_entry_query
cur.execute(get_timestamp)
try:
ts = cur.fetchone()[0]
except:
ts = 0
and use the ts value to add to the next entry. I'm new to Django and DRF, but I assume that is a proper way to do that correctly or at least more pythonic, if anyone could help it would be amazing.
Related
I have a model:
class Film(models.Model):
title = models.CharField(max_length=250)
starring = models.CharField(max_length=250)
description = models.CharField(max_length=500)
rating = models.CharField(max_length=2, choices=(('1','U'),('2','PG'),('3','12A'),('4','12'),('5','15'),('6','18')),default='18')
length = models.IntegerField()
def __str__(self):
return f"{self.title}, {self.rating}"
and a serialiser:
class FilmSerializer(serializers.ModelSerializer):
class Meta:
model = Film
fields = ('title','description','starring','rating','length')
def to_representation(self, instance):
data = super().to_representation(instance)
hours = math.floor(int(data['length']) / 60)
minutes = int(data['length']) % 60
data['length'] = f"{hours}h {minutes}m"
return data
and an api view:
class FilmList(ListAPIView):
queryset = Film.objects.all()
serializer_class = FilmSerializer
filter_backends = (DjangoFilterBackend,)
filterset_fields = ('rating',)
When i use the Django Rest frame work I can filter by the rating, but only if i remove the choices definition from the model. When the choices definition is present on the 'rating' then the filter returns nothing at all.
I would actually like to use that to filter on the 'rating.' Is there a way round this?
thanks
I have any models and one Manager
app/models.py
class castratedListStudent(models.Manager):
use_in_migrations = False
def get_query_set(self):
return super().get_query_set().filter(isOn=1)
class student(models.Model):
id = models.AutoField(primary_key=True)
firstName = models.CharField(max_length=20)
lastName = models.CharField(max_length=20)
isOn = models.BooleanField()
default_manager = castratedListStudent()
objects = castratedListStudent()
class discipline(models.Model):
id = models.AutoField(primary_key=True)
nameDiscipline = models.CharField(max_length=100, null=False)
itemIdToDiscip = models.ForeignKey(item, on_delete=models.CASCADE, default=1)
class listOfStudForDiscipline(models.Model):
id = models.AutoField(primary_key=True)
discipListId = models.ForeignKey(discipline, on_delete=models.CASCADE)
studId = models.ForeignKey(student, on_delete=models.CASCADE)
I am using django inline
accounts/admin.py
class discipStudentInline(admin.TabularInline):
model = listOfStudForDiscipline
admin.TabularInline.verbose_name = 'Student'
extra = 0
def has_change_permission(self, request, obj=None):
return False
def get_queryset(self, request):
return self.model.objects.filter(studId__isOn=1)
class disciplineAdmin(admin.ModelAdmin):
model = discipline
inlines = [discipStudentInline]
The Inline form is displayed on the HTML page and filter (studId__isOn=1) works. But the problem is that on the HTML page below there is a field that allows you to add another student and the list of students is not filtered by the filter rule(studId__isOn=1) When I check in the DEBUG_SQL console, I can see how the query goes without the WHERE expression "FROM journal_student".
(0.000) SELECT `journal_listofstudfordiscipline`.`id`, `journal_listofstudfordiscipline`.`discipListId_id`, `journal_listofstudfordiscipline`.`studId_id` FROM `journal_listofstudfordiscipline` INNER JOIN `journal_student` ON (`journal_listofstudfordiscipline`.`studId_id` = `journal_student`.`id`) WHERE (`journal_student`.`isOn` = 1 AND journal_listofstudfordiscipline`.`discipListId_id` = 1) ORDER BY `journal_student`.`lastName` DESC; args=(True, 1)
(0.000) SELECT `journal_student`.`id`,..., `journal_student`.`descriptionStudent` FROM journal_student` ORDER BY `journal_student`.`lastName` ASC, `journal_student`.`firstName` ASC; args=()
I couldn't solve the problem using the model Manager.
I solved the problem. It turned out that after django version 1.7, the get_query_set() method was renamed to get_queryset(). And the Manager will now look like this:
class castratedListStudent(models.Manager):
use_in_migrations = False
def get_query_set(self):
return super(liveListStudent, self).get_queryset().filter(isOn=1)
I'm having some trouble querying for my CalculatedAmt field in my database. In fact, according to the error code, the field does not even exist. However, I have included it in my Models.py and it can even be seen in my admin interface on Django.
Here are my codes:
Model.py - I didn't join the tables because I didn't need the join for my queries
class Customer(models.Model):
Customer_Name_P = models.CharField(max_length=30, default="missing")
Customer_TelNo = models.CharField(max_length=8, default="missing")
Postal_Code = models.CharField(max_length=6, default="missing")
def __str__(self):
return "%s" % self.Customer_Name_P
class Transaction(models.Model):
DocRef = models.CharField(max_length=10,default="missing")
DocDate = models.DateField()
AcCrIsMinus1 = models.CharField(max_length=10,default="missing")
AcCurWTaxAmt = models.CharField(max_length=10,default="missing")
HomeWTaxAmt = models.CharField(max_length=10,default="missing")
CalculatedAmt = models.CharField(max_length=10, default="missing")
ProjectCode = models.CharField(max_length=10,default="missing")
Location = models.CharField(max_length=10,default="missing")
Sales_Person = models.CharField(max_length=10,default="missing")
AcCode = models.CharField(max_length=8,default="missing")
Customer_Name = models.CharField(max_length=30,default="missing")
def __str__(self):
return "%s" % self.id
class Salesperson(models.Model):
Sales_Person_P = models.CharField(max_length=10,default="missing",primary_key=True)
Sales_Person_Name = models.CharField(max_length=10,default="missing")
Sales_Person_Contact = models.CharField(max_length=10,default="missing")
def __str__(self):
return "%s" % self.Sales_Person_P
class Account(models.Model):
AcCode_P = models.CharField(max_length=8, default="missing",primary_key=True)
Customer_Name = models.CharField(max_length=30,default="missing")
AcCur = models.CharField(max_length=3, default="missing")
def __str__(self):
return "%s" % self.AcCode_P
Query in shell (for a table):
Transaction.objects.all().filter(Sales_Person=Sales_Person).values('DocRef','DocDate','AcCrIsMinus1','HomeWTaxAmt','ProjectCode','Customer_Name','Location')
Error Message:
django.core.exceptions.FieldError: Cannot resolve keyword 'CalculatedAmt' into field. Choices are: AcCode, AcCrIsMinus1, AcCurWTaxAmt, Customer_Name, DocDate, DocRef, HomeWTaxAmt, Location, ProjectCode, Sales_Person, id
Here's a screenshot of a Transaction instance from the admin interface:
screenshot
Screenshot of the output for python manage.py showmigrations:
screenshot
Screenshot of migrations 0001_initial file
screenshot
Thank you!
This error does not say that the field is missing. The FieldError exception is raised when there is a problem with a model field. This can happen for several reasons:
A field in a model clashes with a field of the same name from an
abstract base class
An infinite loop is caused by ordering
A keyword cannot be parsed from the filter parameters
A field cannot be determined from a keyword in the query parameters
A join is not permitted on the specified field
A field name is invalid A query contains invalid order_by arguments
Just for your information, for a field which does not exist there is a FieldDoesNotExist exception. It is raised by a model’s _meta.get_field() method when the requested field does not exist on the model or on the model’s parents.
The error is because you are fetching all() first then try to filter. When you fetch all you get all fields and then not include CalculatedAmt in your values.
t = Transaction.objects.filter(Sales_Person__iexact=Sales_Person)
t object will be containing all the field of Transaction so no need for .values, you can retrieve them by t.CalculatedAmt for example. P.s. ixact means exact matching without caring for case-sensitiveness.
Moreover, I assume you have tried to connect 2 models together with Sales_Person field. But you are doing it in the wrong way.
You should use one of the OnetoOne, ForeignKey or ManytoMany relationships. I will use ForeignKey assuming that a salesperson can have many transactions but each transaction can only belong to one person.
class Transaction(models.Model):
DocRef = models.CharField(max_length=10,default="missing")
DocDate = models.DateField()
AcCrIsMinus1 = models.CharField(max_length=10,default="missing")
AcCurWTaxAmt = models.CharField(max_length=10,default="missing")
HomeWTaxAmt = models.CharField(max_length=10,default="missing")
CalculatedAmt = models.CharField(max_length=10, default="missing")
ProjectCode = models.CharField(max_length=10,default="missing")
Location = models.CharField(max_length=10,default="missing")
Sales_Person = models.ForeignKey('Salesperson', on_delete=models.CASCADE)
AcCode = models.CharField(max_length=8,default="missing")
Customer_Name = models.CharField(max_length=30,default="missing")
def __str__(self):
return "%s" % self.id
class Salesperson(models.Model):
Sales_Person_P = models.CharField(max_length=10,default="missing",primary_key=True)
Sales_Person_Name = models.CharField(max_length=10,default="missing")
Sales_Person_Contact = models.CharField(max_length=10,default="missing")
def __str__(self):
return "%s" % self.Sales_Person_P
I am getting below error when I use auto_now_add in my Model Form.
TypeError: __init__() got an unexpected keyword argument 'auto_now_add'
Here is my model field
modified = models.DateTimeField(blank = True)
Declaration in form. I have seen in one of the posts DateTimeField Not Working
to add initial = datetime.datetime.now for auto populating
import datetime
modified = forms.DateTimeField(initial = datetime.datetime.now) - When I use this no error is coming but datetime was not auto populating.
I have used the same in self.fields['modified'] - Still no use
Any of the above statements were not working. Some one help me on this.
I am pasting all my model class and Model Form here
Model Class
class Users(models.Model):
name = models.CharField(max_length = 100)
role = models.ForeignKey(RolesConfig, db_column = 'role')
level = models.ForeignKey(LevelConfig, db_column = 'level')
team_name = models.ForeignKey(TeamNamesConfig, db_column = 'team_name')
location = models.ForeignKey(LocationConfig, db_column = 'location')
modified = models.DateTimeField(blank = True)
class Meta:
db_table = u'users'
def __str__(self):
return "%s" % (self.ldap)
def __unicode__(self):
return u'%s' % (self.ldap)
I have modified the field in phpmyadmin
This is my ModelForm
class TargetForm(forms.ModelForm):
modified = forms DateTimeField(initial = datetime.datetime.now)
def __init__(self, *args, **kwargs):
super(MMPodTargetForm, self).__init__(*args, **kwargs)
self.fields['modified'] = forms.DateTimeField(initial = datetime.datetime.now)
class Meta:
model = models.Users
I need to get current date and time autopopulated in the form, when the form loads. Tell me whats wrong in my code.
I think the error is because you're adding the auto_now_add extra argument to your form instead of to your mode. Try changing your model to the following to see if that fixes the problem (untested):
class Users(models.Model):
name = models.CharField(max_length = 100)
role = models.ForeignKey(RolesConfig, db_column = 'role')
level = models.ForeignKey(LevelConfig, db_column = 'level')
team_name = models.ForeignKey(TeamNamesConfig, db_column = 'team_name')
location = models.ForeignKey(LocationConfig, db_column = 'location')
modified = models.DateTimeField(auto_now = True)
class Meta:
db_table = u'users'
def __str__(self):
return "%s" % (self.ldap)
def __unicode__(self):
return u'%s' % (self.ldap)
This question is related to this one
Remove all the elements in a foreign key select field
I had a foreign key field in my model which was getting pre-populated by its data and I wanted the select list to be empty. I did achieve that but the validation fails when I submit the form.
The error says "Select a valid choice option. 1 is not one of the available choices).
These are my models
class RecipeIngredient(models.Model):
recipe = models.ForeignKey(Recipe)
ingredient = models.ForeignKey(Ingredient)
serving_size = models.ForeignKey(ServingSize)
quantity = models.IntegerField()
order = models.IntegerField()
created = models.DateTimeField(auto_now_add = True)
updated = models.DateTimeField(auto_now = True)
class RecipeIngredientForm(forms.ModelForm):
serving_size = forms.ChoiceField(widget=forms.Select())
class Meta:
serving_size = forms.ChoiceField(widget=forms.Select())
model = RecipeIngredient
fields = ('ingredient', 'quantity', 'serving_size')
widgets = {
'ingredient': forms.TextInput(attrs={'class' : 'recipe_ingredient'}),
'quantity': forms.TextInput(),
'serving_size' : forms.Select(attrs={'class' : 'ddl'}),
}
I get an error on the third line
recipeIngredients = models.RecipeIngredientFormSet(request.POST)
print(recipeIngredients.errors)
objRecipeIngredients = recipeIngredients.save(commit=False)
I want the select box to be empty because it gets populated by an ajax call. Any ideas what to do so the model passes the validation?
EDIT
Serving Size Model
class ServingSize(models.Model):
name = models.CharField(max_length = 255)
unit = models.CharField(max_length = 125)
food_group = models.ForeignKey(FoodGroup)
created = models.DateTimeField(auto_now_add = True)
updated = models.DateTimeField(auto_now = True)
objects = models.Manager()
dal_objects = ServingSizeManager()
def __unicode__(self):
return self.name;
First, why do you have serving_size in the Meta class?
I would use an extra field in the ModelForm and leave out serving_size field altogether.
class RecipeIngredientForm(forms.ModelForm):
mycustomfield = forms.ChoiceField(widget=forms.Select())
class Meta:
model = RecipeIngredient
exclude = ('serving_size', 'created', 'updated') #etc
Then in the view I would manipulate the form to assign a valid ServingSize to the serving_size field.
[EDIT]
Alright, your actual implementation will depend on what you are pulling through ajax and how. But see the following code: -
Your form: -
class CustomRecipeIngredientForm(forms.ModelForm):
recipe = forms.ModelChoiceField( Recipe.objects.all(),
widget=forms.Select(attrs={'class':'customclass',}))
ingredient = forms.ModelChoiceField( Ingredient.objects.all(),
widget=forms.Select(attrs={'class':'recipe_ingredient',}))
my_custom_serving_size_field = forms.ChoiceField(widget=forms.Select(attrs={'class':'ddl',}))
quantity = forms.IntegerField()
order = forms.IntegerField()
class Meta:
model = RecipeIngredient
exclude = ('serving_size', 'created', 'updated',)
Pull your data through ajax into the my_custom_serving_size_field
Your view: -
def my_view(request):
if request.method == 'POST':
form = CustomRecipeIngredientForm(data=request.POST)
if form.is_valid():
new_recipe_ingredient = form.save(commit=False)
new_recipe_ingredient.serving_size = ServingSize.objects.get(pk=form.cleaned_data['my_custom_serving_size_field'])
new_recipe_ingredient.save()
return HttpResponseRedirect(reverse('redirect_to_wherever'))
else:
form = CustomRecipeIngredientForm()
return render_to_response('path/to/my_template.html', {'form': form}, context_instance=RequestContext(request))
Of course, your ServingSize.objects.get() logic will depend on what your are pulling through ajax and how. Try something along these lines and let us know.
Looks like you want a ModelChoiceField, which
Allows the selection of a single model
object, suitable for representing a
foreign key