I'm trying to create a model based on the Google Map API.
If the object does not exists, I want to save the name, address, longitude, latitude and google place ID. Below is my code: However, when I run it, it goes into a loop and does stop checking Google Map. Can you tell me what is wrong?
class Place(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
address = models.CharField(max_length=200, null=True, blank=True)
logitude = models.CharField(max_length=20, null=True, blank=True)
latitude = models.CharField(max_length=20, null=True, blank=True)
id_google = models.CharField(max_length=50, null=True, blank=True)
date_created = models.DateTimeField(_('date created'), default=timezone.now)
date_modified = models.DateTimeField(_('date_modified'), auto_now=True)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
try:
place = Place.objects.get(name=self.name)
except Place.DoesNotExist:
gmaps = googlemaps.Client(key=settings.GOOGLE_MAPS_API_KEY)
geocode_result = gmaps.geocode(self.address)
place = Place(name=self.name,
address=geocode_result[0]['formatted_address'],
logitude=geocode_result[0]['geometry']['location']['lng'],
latitude=geocode_result[0]['geometry']['location']['lat'],
id_google=geocode_result[0]['place_id'],
)
place.save()
return place
You call place.save() in the save(..) method, and thus triggering another save. You probably can just edit the item inplace, and then save it by using a super().save() call:
class Place(models.Model):
# ...
def save(self, *args, **kwargs):
try:
place = Place.objects.get(name=self.name)
except Place.DoesNotExist:
gmaps = googlemaps.Client(key=settings.GOOGLE_MAPS_API_KEY)
geocode_result = gmaps.geocode(self.address)[0]
self.address = geocode_result['formatted_address']
location = geocode_result['geometry']['location']
self.logitude = location['lng']
self.latitude = location['lat']
self.id_google = geocode_result['place_id']
super().save(*args, **kwargs)
Related
Have the following models
class FootballWebsite(models.Model):
"""Football service website."""
url = models.URLField, unique=True)
#football service
id = models.CharField(primary_key=True,
#is this domain blocked
blocked = models.BooleanField(default=False)
#is it online or offline
online = models.BooleanField(default=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
sub_categories = models.ForeignKey(SubCategory, default=1)
referral = models.TextField(blank=True)
mirror = models.ForeignKey('FootballWebsite', blank=True, null=True)
rank = models.PositiveIntegerField(default=0, blank=True, null=True)
screenshot = models.BooleanField(default=False)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return u'%s' % (self.url)
"""The datetime when the football service was last seen online"""
try:
return self.footballwebsitestatus_set.filter(online=True).latest('time').time
except FootballWebsiteStatus.DoesNotExist:
return None
class FootballWebsiteDescription(models.Model):
"""Football service website description."""
about = models.ForeignKey(Footballebsite)
title = models.TextField(blank=True, null=True)
keywords = models.TextField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
relation = models.URLField(blank=True, null=True)
subject = models.TextField(blank=True, null=True)
type = models.TextField(blank=True, null=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
language = models.TextField(null=True, blank=True)
contactInformation = models.TextField(null=True, blank=True)
officialInfo = models.BooleanField(default=False)
slug = AutoSlugField(populate_from=['title'], allow_duplicates=True, null=True)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return unicode(self.about.url)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(FootballebsiteDescription, self).save(*args, **kwargs)
def __unicode__(self):
return u'%s' % (self.title)
I have a huge amount of links, and i would like to bulk assign them into a category or mark them as blocked based on identical title slug.
Managed to at least get a list of title_slugs with the code below, but the following step, i would like to get an inline list with all sites that have an identical title_slug and bulk assign those all in their a category
class FootballWebsiteInline(admin.TabularInline):
model = FootballWebsite
class FootballWebsiteDescriptionAdmin(admin.ModelAdmin):
list_display = ['show_slug']
def show_slug(self, obj):
return format_html("<a href='{url}'>{url}</a>", url=obj.slug)
inlines = [
FootballWebsiteInline,
]
Above code obviously doesn' t work, since the title slug which can appear many times is not a primary key.
Is it possible to get an inline list based on the title slug in this case which is not a primary key at all, or am i going about this the wrong way?
When possible at all, some further tweaking would be to group the identical title slugs
I want to create a countdown timer target that will be added into date_target model, using override save method in models.py, the time will countdown differently based on it's variety.
import datetime
class CustomerVariety(models.Model):
variety = models.CharField(max_length=100, null=True)
def __str__(self):
return self.variety
class Customer(models.Model):
cardnumber = models.CharField(max_length=15, null=False)
name = models.CharField(max_length=100, null=False)
date_in = models.DateTimeField(auto_now_add=False, auto_now=False, blank=True,
null=True)
date_target = models.DateTimeField(auto_now_add=False, null=True)
variety = models.ForeignKey(CustomerVariety,
on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.pk:
if self.variety == "Priority Customer":
self.date_target = self.date_in + datetime.timedelta(days=3)
elif self.variety == "Secondary Customer":
self.date_target = self.date_in + datetime.timedelta(days=5)
super(Customer, self).save(*args, **kwargs)
when i pass value into form and save it, why date_target models doesn't full fill the value ?
I am working with slug on my model. Although, the entries for slug are not unique. When I try to go to a url containing slug, it says get() returned more than one object and I understand that it is because the entries are not unique. How am I supposed to change the slug a bit, if identical entries occur?
model
class Cabin(models.Model):
centre_name = models.ForeignKey(Centre, on_delete=models.CASCADE )
code = models.CharField(max_length=8, unique=True, default=unique_rand)
total_seats = models.IntegerField(blank='False')
category=models.CharField(max_length=100, default=False)
booked_date=models.DateField(blank='False')
released_date=models.DateField(blank='False')
price=models.IntegerField(blank=False, default=None)
slug = models.SlugField(unique=False,default=None,blank=True)
objects = UserManager()
def save(self, *args, **kwargs):
self.slug = slugify(self.category)
super(Client, self).save(*args, **kwargs)
First of all it might be better to set unique=True, such that this can never happen, furthermore you can :
class Cabin(models.Model):
centre_name = models.ForeignKey(Centre, on_delete=models.CASCADE )
code = models.CharField(max_length=8, unique=True, default=unique_rand)
total_seats = models.IntegerField(blank='False')
category=models.CharField(max_length=100, default=False)
booked_date=models.DateField(blank='False')
released_date=models.DateField(blank='False')
price=models.IntegerField(blank=False, default=None)
slug = models.SlugField(unique=True,default=None,blank=True)
objects = UserManager()
def save(self, *args, **kwargs):
slug = originalslug = slugify(self.category)
i = 0
while Cabin.objects.exist(slug=slug):
slug = '{}{}'.format(originalslug, i)
i += 1
self.slug = slug
super(Client, self).save(*args, **kwargs)
We here thus increment i until we found a slug that is not yet used.
Note that there exists an AutoSlugField in the django-extensions package [PyPi], that automates this slug procedure. For example:
from django.db import models
from django_extensions.db.fields import AutoSlugField
class Cabin(models.Model):
centre_name = models.ForeignKey(Centre, on_delete=models.CASCADE )
code = models.CharField(max_length=8, unique=True, default=unique_rand)
total_seats = models.IntegerField(blank='False')
category=models.CharField(max_length=100, default=False)
booked_date=models.DateField(blank='False')
released_date=models.DateField(blank='False')
price=models.IntegerField(blank=False, default=None)
slug = AutoSlugField(populate_from='category')
objects = UserManager()
is there any way to call a specific model custom method from a view? i need to subtract or increment depending on the view a field on my model, I want to create a button for each of the two options and after imputing that data update the field in my database. if so how can i go about implementing it, currently my save method is doing the two operations at once
models.py
class Items(models.Model):
nombre = models.CharField(max_length=250)
descripcion = models.CharField(max_length=250)
codigo_proveedor = models.CharField(max_length=250)
categoria = models.ForeignKey('Categorias', on_delete=models.CASCADE)
c_minima = models.PositiveIntegerField()
c_actual = models.PositiveIntegerField()
c_descuento = models.PositiveIntegerField(blank=True)
c_incremento = models.PositiveIntegerField(blank=True)
proveedor = models.ForeignKey('Proveedores', on_delete=models.CASCADE)
carrito = models.ForeignKey('Carrito', on_delete=models.CASCADE, null=True )
p_unitario = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True )
total = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
material = models.ForeignKey(Materiales, null=True, blank=True)
tipo = models.ForeignKey(Tipo, null=True, blank=True)
active = models.BooleanField()
def save(self, *args, **kwargs):
self.c_actual = self.c_actual - self.c_descuento
self.c_actual =self.c_actual + self.c_incremento
self.total = self.c_actual * self.p_unitario
super(Items, self).save(*args, **kwargs)
def __str__(self):
return '%s %s %s %s' % (self.nombre, str(self.categoria), str(self.c_actual), str(self.total))
You could use an instance method on the model e.g. exactly like the get_absolute_url().
You can add 3 methods in the model definition increment, decrement and total and write the respective logic in there.
So the view in the views.py file be something like
def some_view(request, *args, **kwargs):
#read the post data values from req
#create model instance
data = Items( #key value pairs)
#read from req to increament or decrement
if incr:
data.increament()
else:
data.decrement()
data.total()
data.save()
return render( ... )
I have a Property Model as follows =
class Property(models.Model):
property_type = models.CharField(max_length=255, default='Apartment')
specifications = models.CharField(max_length=255, default='Basic')
built_up_area = models.FloatField(max_length=6, null=False, default=0)
total_area = models.FloatField(null=False, default=0)
number_of_bedrooms = models.CharField(max_length=3, default=1)
number_of_bathrooms = models.CharField(max_length=3, default=1)
number_of_parking_spaces = models.CharField(max_length=2, default=0)
address_line_one = models.CharField(max_length=255, null=False)
address_line_two = models.CharField(max_length=255, null=True, default=None)
connectivity = models.CharField(max_length=255, default=None, null=True)
neighborhood_quality = models.CharField(max_length=255, default=None,
null=True)
comments = models.CharField(max_length=255, default=None, null=True)
city = models.ForeignKey('City')
state = models.ForeignKey('State')
pin_code = models.ForeignKey('PinCode')
developer = models.ForeignKey('Developer', null=True, default=None)
owner = models.ForeignKey('Owner', null=True, default=None)
created_by = models.ForeignKey('custom_user.User')
project = models.ForeignKey('Project')
def __unicode__(self):
return self.property_type
class Meta:
verbose_name_plural = 'Properties'
And a City model as follows -
class City(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(City, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
Now I want to make a single form where I can enter the Property details and while entering the city, I can enter the name of the city instead of selecting from the dropdown list.
So how do I create the inline formset using the inlineformset_factory to create the form?
==EDIT==
I've tried to use the following code to create the formset
CityFormset = inlineformset_factory(City, Property,
fields=('city',),
extra=0,
min_num=1,
can_delete=False)
You've misunderstood what an inline formset is. It's for editing the "many" side of a one-to-many relationship: that is, given a parent model of City, you could edit inline the various Properties that belong to that city.
You don't want a formset at all to simply edit the single City that a property can belong to. Instead, override the city field within your Property form to be a TextField, and either create a new City or find an existing one in the clean_city method.
class PropertyForm(forms.ModelForm):
city = forms.TextField(required=True)
class Meta:
model = Property
exclude = ('city',)
def __init__(self, *args, **kwargs):
super(PropertyForm, self).__init__(*args, **kwargs)
if self.instance and not self.data:
self.initial['city'] = self.instance.city.name
def save(self, commit=True):
city_name = self.cleaned_data['city']
city, _ = City.objects.get_or_create(name=city_name)
instance = self.save(commit=False)
instance.city = city
if commit = True:
instance.save()
return instance