I have the following model
class DNS(models.Model):
domain = models.ForeignKey(Domain)
host_start = models.CharField(max_length=150, blank=True, null=True)
type = models.SmallIntegerField(max_length=1, default=0, choices=DNS_CHOICE)
value = models.SmallIntegerField(max_length=3, default=0, blank=True, null=True)
ip = models.IPAddressField(blank=True, null=True)
host_end = models.ForeignKey("DNS", blank=True, null=True)
other_end = HostnameField(max_length=150, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
sticky = models.BooleanField(default=0)
other = models.BooleanField(default=0)
When I try to init a form with just foreignkeys on host_end.. it always shows all entries in the DNS table
domain = Domain.objects.get(id=request.GET['domain'], user=request.user, active=1)
form = DNSFormCNAME(initial={'ip': settings.MAIN_IP, 'type': request.GET['type'], 'host_end': DNS.objects.filter(domain=domain)})
I just want the zones that match that domain.. not all domains.
Initial data to a choice or foreign key field is used to determine what is selected in that field, not what the available options are. If you want to determine the list of options, you need to override the form's __init__ method and do it there.
class DNSFormCNAME(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.domain = kwargs.pop('domain', None)
super(DNSFormCNAME, self).__init__(*args, **kwargs)
if self.domain:
self.fields['host_end'].queryset = DNS.objects.filter(domain=domain)
Related
I am trying to override the save method in a model with logic to update a couple of many to many fields. Using print statements I can see values updating as expected but the values are not persisted after save.
In the below model the change_access_flag is changing as expected with a signal, the prints are executing with the appropriate values, but the allowed_departments and allowed_communities fields are not updating with the printed values.
Model
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
full_name = models.CharField(null=True, blank=True, max_length=50)
payroll_id = models.CharField(null=True, max_length=20)
position = models.ForeignKey(Position, null=True, on_delete=models.SET_NULL)
primary_community = models.ForeignKey(Community, null=True, on_delete=models.CASCADE, related_name="primary_community")
region = models.CharField(max_length=2, choices=RegionChoices.choices, blank=True, null=True)
allowed_communities = models.ManyToManyField(Community, blank=True, related_name="allowed_community")
allowed_departments = models.ManyToManyField(Department, blank=True)
access_change_flag = models.BooleanField(default=False)
def __str__(self):
return f'{self.user.first_name} {self.user.last_name}'
class Meta:
verbose_name_plural = "People"
ordering = ['position__position_code', 'user__last_name', 'full_name']
def save(self, *args, **kwargs):
#Set Full Name field
if self.user.last_name:
self.full_name = f'{self.user.first_name} {self.user.last_name}'
super().save(*args, **kwargs)
#Change flag set in signals, set for events that require updating access settings
if self.access_change_flag:
self.access_change_flag = False
#Allowed community access
access_level = self.position.location_access_level
self.allowed_communities.clear()
if access_level == 'R':
if self.primary_community.community_name == '#':
region = self.region
else:
region = self.primary_community.region
if region is not None:
communities = Community.objects.filter(region=region)
self.allowed_communities.set(communities)
self.allowed_communities.add(self.primary_community)
elif access_level == 'A':
communities = Community.objects.filter(active=True)
self.allowed_communities.set(communities)
else:
communities = self.primary_community
self.allowed_communities.add(communities)
print(self.allowed_communities.all())
#Allowed department access
dept_access = self.position.department_only_access
if dept_access:
depts = [self.position.department]
else:
depts = Department.objects.filter(active=True)
self.allowed_departments.set(depts)
print(self.allowed_departments.all())
super().save(*args, **kwargs)
I have tried variations of set, clear, add, moving the super.save() around, and placing the logic in a signal but nothing seems to work. I have tested initiating save from both a model form through a view and admin.
Let me answer in quotes. You can find the source in this section.
If you wish to update a field value in the save() method, you may also
want to have this field added to the update_fields keyword argument.
This will ensure the field is saved when update_fields is specified.
Also read here
Specifying update_fields will force an update.
So try to call the super().save(*args, **kwargs) method at the end with defining the argument update_fields. This will force the update of your model regarding the specified fields.
Let me know how it goes.
How can I increment an invoice number with a prefix “INV” and number that increments ‘0001’, ‘0002’, ‘0003’......and so on..... when the user creates an invoice?
class Invoice(model.Models):
clients_name = models.ForeignKey(Clients, on_delete=models.CASCADE, blank=True,null=True)
invoice_number = invoice_number = models.CharField(max_length=200, blank=True, null=True)
Once the user creates/saves the invoice form, the hidden field(invoice field) should be auto-filled with invoice number
e.g.
client
invoice
client_name1
INV-001
client_name2
INV-002
client_name4
INV-003
client_name8
INV-004
You can make this process in save model method:
class Invoice(model.Models):
clients_name = models.ForeignKey(Clients, on_delete=models.CASCADE, blank=True,null=True)
invoice_number = models.CharField(max_length=200, blank=True, null=True)
def save(self):
if not self.invoice_number and self.pk is None:
last_invoice = Invoice.objects.all().order_by("-pk").first()
last_pk = 0
if last_invoice:
last_pk = last_invoice.pk
self.invoice_number = "INV-" + str(last_pk+1).zfill(3)
super(Invoice, self).save()
I am using the primary key for incremental number, but you can use another field in the model for making this task.
I am trying to order a queryset by distance from an input location. I am able to order the original queryset that contains the point fields, however when I use that queryset to filter a query on another model then it returns the queryset unordered. The code is as follows:
Models:
class EnglandSpine(models.Model):
urn = models.CharField(db_column='URN', primary_key=True, max_length=10)
schname = models.CharField(db_column='SCHNAME', max_length=150, blank=True, null=True)
postcode = models.ForeignKey(Postcodes3, to_field='pc', on_delete=models.CASCADE, db_column='POSTCODE', max_length=10, blank=True, null=True)
class Postcodes3(models.Model):
gid = models.AutoField(primary_key=True)
pc = models.CharField(max_length=10, blank=True, null=True, unique=True)
latitude = models.FloatField(blank=True, null=True)
longitude = models.FloatField(blank=True, null=True)
the_geom = gis_models.PointField(blank=True, null=True)
def __str__(self):
return self.pc
objects = GeoManager()
class Meta:
managed = True
db_table = 'postcodes3'
I am able to retrieve an ordered list of postcodes with the following view
views.py
class PCSearch(TemplateView, SingleTableView):
template_name = 'schoolData/pcs.html'
def get(self, request):
form = PostSearch()
return render(request, self.template_name, {'form':form})
def post(self, request):
form = PostSearch(request.POST)
if form.is_valid():
pcps = form.cleaned_data['Postcode']
pc = pcps.replace(' ','')
d = form.cleaned_data['Distance']
ss = form.cleaned_data['schtype']
gs = form.cleaned_data['gentype']
adms = form.cleaned_data['seltype']
pcr = Postcodes3.objects.get(pc=pc)
area = (pcr.the_geom, Distance(mi=d))
pcs = Postcodes3.objects.filter(the_geom__distance_lte=area).values('pc')
pcss = pcs.annotate(distance=GeometryDistance("the_geom", pcr.the_geom)).order_by("distance")
Finally I would pass the pcss variable through one more filter to get all the schools...
results = EnglandSpine.objects.filter(postcode__in=pcss)
But this does not return the query set in any order?
My second approach was to set the postcode field in EnglandSpine as a foreign key to Postcodes3 pc and perform Geometry Distance search, but it cant find the related object postcodes.the_geom.
Really stuck here and after countless hours I cannot find a specific example that relates to my issue.
Any help would be much appreciated.
Thanks,
I need to write any data to ManyToManyField via Model's form in the template, but i get an error like "... needs to have a value for field "id" before this many-to-many relationship can be used.". It shows when I try to use self.service("service" is my ManyToManyField) in my overrided save() method. I know that ManyToManyField is not basic field and it returns something like queryset, but how can i manipulate data inside save() method, because "self.service" doesn't work.
# models.py
class Appointments(models.Model):
name = models.CharField(max_length=200, db_index=True, verbose_name='Имя, фамилия')
tel = models.CharField(max_length=200, db_index=True, verbose_name='Номер телефона')
e_mail = models.CharField(max_length=200, blank=True, db_index=True, verbose_name='E-mail')
car = models.ForeignKey('Cars', null=True, on_delete=models.PROTECT, verbose_name='Тип автомобиля')
num_car = models.CharField(max_length=200, null=True, db_index=True, verbose_name='Гос.номер автомобиля')
**service = models.ManyToManyField(Services, verbose_name='Тип услуги')**
date_created = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Дата публикации заявки')
date_service = models.DateField(db_index=True, verbose_name='Дата')
time_service = models.TimeField(db_index=True, help_text="Введите время в таком формате: 15:00", verbose_name='Время')
price = models.CharField(max_length=50, db_index=True, null=True, verbose_name='Цена')
def save(self, *args, **kwargs):
for i in Services_prices.objects.all():
ccar = i.car
sservice = i.service
for d in self.service:
if self.car == ccar and d == sservice:
self.price = i.price
break
elif ccar == None and d == sservice:
self.price = i.price
break
super().save(*args, **kwargs)
# forms.py
class AppointmentForm(forms.ModelForm):
service = forms.ModelMultipleChoiceField(queryset=Services.objects.all(), required=False, widget=forms.CheckboxSelectMultiple())
class Meta:
model = Appointments
fields = ('name', 'tel', 'e_mail', 'car', 'num_car', 'service', 'date_service', 'time_service')
In order to have a many_to_many relation between two objects, you need primary keys of the both objects. Before calling super's save, your model does not have a primary key yet.
In your overriden save method, call super first, (e.g.super().save(*args, **kwargs)) then do your stuff, then save again.
How to get exactly the series that is specified in the URL, but the name of all series is the same, and they should be the same, but it takes only the URL of the series itself, that is, it searches only for the URL series, but not how, so that this series was in The series which is specified in the URL and also was in the season exactly the volume that is specified in the URL here is url
Url works fine but I can not go to the right series!
urlpatterns = [
url(r'^$', homeview, name='homeview'),
url(r'^subscribe/$', validate_email, name='subscribe'), # /series/
url(r'^(?P<serial_slug>[\w-]+)/$', post_of_serial, name='post_of_serial'), # /series/Prison_Break/
url(r'^(?P<serial_slug>[\w-]+)/(?P<season_slug>[\w-]+)/$', post_of_season, name='post_of_season'), # /series/Prison_Break/season_5/
url(r'^(?P<serial_slug>[\w-]+)/(?P<season_slug>[\w-]+)/(?P<series_slug>[\w-]+)/$', post_of_serie, name='post_of_serie'), # /series/Prison_Break/season_5/2/
]
Models
class Series(models.Model):
id = models.AutoField(primary_key=True)
rus_name = models.CharField(max_length=60)
eng_name = models.CharField(max_length=60)
slug = models.SlugField(unique=False)
serial_of_this_series = models.ForeignKey(Serial, on_delete=models.CASCADE, default=True)
season_of_this_series = models.ForeignKey(Season, on_delete=models.CASCADE, default=True)
number_of_series = models.IntegerField(default=0, blank=True, null=True)
description = models.TextField(max_length=700, blank=True, default=None)
size_of_torent_file = models.CharField(max_length=60, default=None)
link_for_dowloand_serie_in_quality_360p = models.CharField(max_length=60, default=None)
link_for_dowloand_serie_in_quality_720p = models.CharField(max_length=60, default=None)
link_for_dowloand_serie_in_quality_1080p = models.CharField(max_length=60, default=None)
rating = models.FloatField(default=0, blank=True)
is_active = models.BooleanField(default=True)
timestamp_rus = models.DateField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
timestamp_eng = models.CharField(max_length=60)
time_of_series = models.DecimalField(max_digits=10, decimal_places=2, default=42)
def get_absolute_url(self):
return reverse('series:post_of_serie', kwargs=
{'serial_slug': self.serial_of_this_series.slug,
'season_slug': self.season_of_this_series.slug,
'series_slug': self.slug})
def __str__(self):
return "%s | %s" % (self.rus_name, self.number_of_series)
class Meta:
ordering = ["-timestamp_rus"]
verbose_name = 'Series'
verbose_name_plural = 'Series'
views.py
def post_of_serie(request, serial_slug=None, season_slug=None, series_slug=None):
serie = get_object_or_404(Series, serial_of_this_series=serial_slug, season_of_this_series=season_slug, slug=series_slug)
#series_2 = Series.objects.filter(serial_of_this_series=serial_slug, season_of_this_series=season_slug, slug=series_slug )
context = {"serie":serie,}
return render(request, 'series.html', context)
Error on the version above
ValueError at /series/Colony/Season_1/episode_1/
invalid literal for int() with base 10: 'Colony'
There was also such an option but there comes an error from such that such a name already exists. In fact the fact that the name of the series and seasons should be the same!
def post_of_serie(request, serial_slug=None, season_slug=None, series_slug=None):
serie = get_object_or_404(Series, slug=series_slug)
context = {"serie":serie,}
return render(request, 'series.html', context)
Try editing your views like this,
def post_of_serie(request, serial_slug=None, season_slug=None, series_slug=None):
serie = get_object_or_404(Series, serial_of_this_series__slug=serial_slug, season_of_this_series__slug=season_slug, slug=series_slug)
context = {"serie":serie,}
return render(request, 'series.html', context)
The serial_of_this_series is a ForeignKey to another table, so when accessing the field, django automatically provides the primary_key of the corresponding table. By looking at your error, it seems that you haven't explicitly specified the slug field as primary_key, then the auto-incrementing integer field which is provided by the django automatically is trying to match with the slug you just provided. I'd recommend to access the corresponding field in the table, like serial_of_this_series__slug, ie, slug field(or whatever the field name is) in Serial table for query filterings.