I have a model of store
models.py
class Store(models.Model):
title = models.CharField(max_length = 50)
point = models.PointField(null = True, blank = True)
deleted = models.BooleanField(default=False)
I set a form to create a store where the latitude and longitude can be converted into a point
forms.py
class StoreForm(forms.ModelForm):
latitude = forms.FloatField(
min_value = -90,
max_value = 90,
required = True,
)
longitude = forms.FloatField(
min_value = -180,
max_value = 180,
required = True,
)
class Meta(object):
model = Store
exclude = ['deleted']
widgets = {'point': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
coordinates = self.initial.get('point', None)
if isinstance(coordinates, Point):
self.initial['longitude'], self.initial['latitude'] = coordinates.tuple
def clean(self):
data = super().clean()
latitude = data.get('latitude')
longitude = data.get('longitude')
point = data.get('point')
if latitude and longitude and not point:
data['point'] = Point(longitude, latitude)
return data
I used this form to add Store in my HTML frontend and when I check my backend data is in there. this form helps to show latitude and longitude fields and when I submit it automatically converts into a point
When I want to update the store I used the exact same form to update, and I can see the previously added latitude and longitude value in charfield(as usual I used the instance to get the value of fields from that specific entry).
The problem is, I can't update the latitude and longitude now. Why?
NB: if you thinking about exclude and hiddeninput widget, this is the way it works, I trieddd different ways, but this way latitude and longitude is added to form point, in other way it is not converted. If you know how to fix that problem please help me
Through some more research through google I found this solution
in views.py I used this code
if form.isvalid():
form.save()
change it into this
if form.is_valid():
f = form.save(commit = False)
new_latitude = request.POST.get('latitude')
new_longitude = request.POST.get('longitude')
x = 'POINT(' + new_longitude + ' ' + new_latitude + ')'
f.point = fromstr(x, srid = 4326)
f.save()
Related
I have an update form with 4 fields to display
3 of them are related to a class to which the form is bound
the last field (country) is only for information and I would like that field to be display in first position
currently, it is displayed at the end of my form...
I tryed to use field_order but country field is ignored...
form.py
class ParametrageForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs):
super(ParametrageForm, self).__init__(*args, **kwargs)
self.request = request
self.language = request.session.get('language')
self.user = request.user.id # id de l'utilisateur
self.user_pays = request.session.get('user_pays') # pays de l'utilisateur
self.user_site_type = request.session.get('user_site_type')
self.user_site = request.session.get('user_site')
instance = Parametrage.objects.get(asp_par_cle = kwargs['instance'].asp_par_cle)
SITE_CONCERNE = Site.option_list_sites(self.language)
if self.language == 'en':
country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_eng
elif self.language == 'fr':
country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_fra
else:
country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_eng
self.fields["country"] = forms.CharField(label = _("Country"),widget=forms.TextInput,initial=country, disabled=True)
self.fields["asp_par_loc"] = forms.ChoiceField(label = _("Site concerned by settings"), widget=forms.Select, choices=SITE_CONCERNE,)
self.fields["asp_par_ale"] = forms.IntegerField(label = _("Stock alert value for this site"), widget=forms.TextInput,)
self.fields["asp_par_con"] = forms.IntegerField(label = _("Stock confort value for this site"), widget=forms.TextInput,)
class Meta:
model = Parametrage
fields = ('asp_par_loc','asp_par_ale','asp_par_con',)
field_order = ['country','asp_par_loc','asp_par_ale','asp_par_con',]
Replace
self.fields["country"] = forms.CharField(label = _("Country"),widget=forms.TextInput,initial=country, disabled=True)
with
country = forms.CharField(label = _("Country"),widget=forms.TextInput,initial=country, disabled=True)
I found how to solve my issue:
I defined 'country' field outside of the init
and then filed_order works
but doing that, I do not have access to my initial country value, set in init (country= Site.objects.get(sit_abr = instance.asp_par_loc).reg.pay.pay_nom_eng)
I must improve my Python understanding...
I have a loop of buttons, ranging from 1-100 (this varies, could be 1-50), if a user selects any of the button it populates an input field e.g 32, 47, 84, 69.
So i have a django view that saves it to the database but it is saved in the database in this format [u'32', u'47', u'84', u'69'] which i know will be regarded as one entity, but i need the numbers to be regarded as separate entity, so that any number that is in the database, wont be selected by any other user.
def game_details(request, id):
template_name = 'app_agent_games/game_details.html'
get_game_id = get_object_or_404(gamesModel, id=id)
context = {
'game_details': get_game_id,
'range': range(1, get_game_id.people + 1)
}
if request.POST:
guesses = request.POST.get('guessed_number', False)
splited = guesses.split(',')
counter = request.POST.get('count_guess', False)
update_game = PlayGameForm(request.POST)
obj = PlayGame()
obj.guessed_number = splited
obj.total_stake = int(get_game_id.amount) * int(counter)
obj.game_id = get_object_or_404(gamesModel, id=id)
obj.agent_id = get_object_or_404(CustomAgent, user_id=request.user.user_id)
obj.save()
return HttpResponseRedirect('/games/details/'+id)
return render(request, template_name, context)
The model structure:
class PlayGame(models.Model):
agent_id = models.ForeignKey(CustomAgent, related_name='agent_game')
game_id = models.ForeignKey(gamesModel, related_name='agent_game_id')
guessed_number = models.CharField(max_length=100)
total_stake = models.IntegerField(default=0)
The model field that saves the list is guessed_number
Sounds like you need a slightly more evolved data model:
class PlayGame(models.Model):
agent_id = models.ForeignKey(CustomAgent, related_name='agent_game')
game_id = models.ForeignKey(gamesModel, related_name='agent_game_id')
total_stake = models.IntegerField(default=0)
class GameNumber(models.Model):
game = models.ForeignKey(PlayGame)
number = models.IntegerField()
user = models.ForeignKey('YourUser', blank=True, null=True)
Then, for example, you create all your numbers 1-100 for your game, and if a user guessed it, set the user FK to be the user who guessed it, else keep the user FK null.
I know this is probably very basic stuff but I'm really having a tough time figuring it out. I have an app that stores sports forecasts for users, so they input the home team, it's score and the visiting team with it's score. The idea is for the app to determine whether the result was a home win, a tie or an away win by comparing the scores on both input boxes.
This is my view:
def inicio(request):
if request.method == "POST":
form = Pronosticos(request.POST)
if form.is_valid():
pronostico = PartidosUsuarios.objects.get_or_create(idUsuario=request.user, idPartido=request.POST.get("idPartido", ""), PaisL=request.POST.get("PaisL", ""), Local=request.POST.get("Local", ""), Visita=request.POST.get("Visita", ""), PaisV=request.POST.get("PaisV", ""), Capturado="Si")
if pronostico.Local > pronostico.Visita:
pronostico.Resultado = "Local"
elif pronostico.Visita > pronostico.Local:
pronostico.Resultado = "Visita"
elif pronostico.Local == pronostico.Visita:
pronostico.Resultado = "Empate"
return render(request, "brasil/inicio.html")
partidos_fifa = PartidosFifa.objects.order_by("Partido")[:64]
context = {"partidos_fifa": partidos_fifa}
return render(request, "brasil/inicio.html", context)
The form:
class Pronosticos(ModelForm):
class Meta:
model = PartidosUsuarios
fields = ["idPartido", "PaisL", "Local", "Visita", "PaisV"]
and the model:
class PartidosUsuarios(models.Model):
idUsuario = models.OneToOneField(User)
idPartido = models.CharField(max_length=20)
PaisL = models.CharField(max_length=250)
Local = models.IntegerField(max_length=11, default=0)
Visita = models.IntegerField(max_length=11, default=0)
PaisV = models.CharField(max_length=250)
Resultado = models.CharField(max_length=250)
Puntos = models.IntegerField(max_length=11, default=0)
Capturado = models.CharField(max_length=10, default="No")
def __unicode__(self):
return unicode(self.idPartido)
The field in question aka where i want the result to be stored is called "Resultado"
Everything works as it should except for this part where i've been getting this error:
AttributeError at /inicio/
'tuple' object has no attribute 'Local'
It's complaining about this line:
if pronostico.Local > pronostico.Visita:
Any help will be greatly appreciated, thanks!
The problem here is the return value from get_or_create(). From the documentation:
Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying whether a new object was created.
So try this instead:
pronostico, _ = PartidosUsuarios.objects.get_or_create(...)
I made a Product class in Django models like :
class Product(models.Model):
title = models.CharField(max_length=255, unique = True)
description = models.TextField()
image_url = models.URLField(verify_exists=True, max_length=200, blank = True, null = True)
quantity = models.PositiveSmallIntegerField(default=0)
And i want to add a sell() method inside this class. well i did like:
def sell(self):
result = self.quantity - 1
return result
I want to change the value in database when just execute P.sell().
when i run it in the shell like this
>>p = Product(title = 'title', description = 'des', quantity = 10)
>>p.save()
>>p.sell()
9 # it shown 9, but the database not changed still 10
but if i continue to do like this
>> p.quantity = p.sell()
>> p.save()
it can change the quantity to 9
but how can i just change the value when i just type p.sell() ?
how could i edit it in models?
Uh...
def sell(self, save=True):
self.quantity -= 1
if save:
self.save()
class EmployeeRating(models.Model):
rating_1 = models.IntegerField(default = 0)
rating_2 = models.IntegerField(default = 0)
rating_3 = models.IntegerField(default = 0)
rating_4 = models.IntegerField(default = 0)
rating_4 = models.IntegerField(default = 0)
total = models.IntegerField(default = 0)
Using a Model Form to take the values, automatically assign values to 'total'.
1. Don't repeat yourself
It seems like a bad idea to have a field in your model containing the total of some other fields in the same model. It would be all too easy to update one and not the other, leaving the fields inconsistent.
So my suggestion is to drop the total field and compute it when you need it.
You can add a method to the EmployeeRating model that computes it in Python:
class EmployeeRating(models.Model):
# ...
#property
def total_rating(self):
return self.rating_1 + self.rating_2 + self.rating_3 + self.rating_4
And if you need to query on the total, you could use extra():
EmployeeRating.objects.extra(
where = ['rating_1 + rating_2 + rating_3 + rating_4 > 10'])
2. Normalize!
The reason why this is awkward is that your model is not fully normalized. If you have multiple ratings attached to an EmployeeRating record, the natural way to implement them is to have a separate table. If you did this, your model would look like this:
class EmployeeRating(models.Model):
# ... other fields, e.g. foreign key to Employee model.
class Rating(models.Model):
employee_rating = models.ForeignKey(EmployeeRating, related_name='ratings')
rating = models.IntegerField()
# ... other fields, e.g. who performed the evaluation, or when it was done.
and then you can use annotate() when you need to get the total:
from django.db.models import Sum
EmployeeRating.objects.annotate(total_rating = Sum('ratings__rating'))
class EmployeeRatingForm(forms.ModelForm):
class Meta:
model = EmployeeRating
def __init__(self, *args, **kwargs):
super(EmployeeRatingForm, self).__init__(*args, **kwargs)
self.fields['total'].widget = forms.HiddenInput()
def save(self, commit=True):
rating = super(EmployeeRatingForm, self).save(commit=False)
rating1 = self.cleaned_data['rating_1']
rating2 = self.cleaned_data['rating_2']
rating3 = self.cleaned_data['rating_3']
rating4 = self.cleaned_data['rating_4']
rating.total = rating1 + rating2 + rating3 + rating4
rating.save()