DJango CreateView not setting DB Key with Class-Based Views - python

I am using CreateView from DJango to save data to the DB. To do this, I am following the instructions here: Form handling with class-based views
According to my understanding, after the data is saved to the DB, the control is to be passed to a type of "success screen" - in this case, for my scenario, control is to be passed to a "details page". The details page is represented by the following URL:
url(r'^owner/(?P<pk>[0-9]+)/contact/details/$', views.MstrstoreheadcontactDetailsView.as_view(),
name='owner-contact-details'),
Below (in the class Mstrstoreheadcontact) the "details page" is being called by the get_absolute_url function (which is part of the Mstrstoreheadcontact model)
from the models.py file
class Mstrstoreheadcontact(models.Model):
tenantid = models.ForeignKey('Mstrauthowner', models.DO_NOTHING, db_column='tenantid', blank=True, null=True)
contactid = models.BigIntegerField(primary_key=True, default=0)
genderid = models.BigIntegerField(blank=True, null=True, default=0)
firstname = models.CharField(max_length=20, blank=True, null=True)
lastname = models.CharField(max_length=20, blank=True, null=True)
officephoneno = models.CharField(max_length=20, blank=True, null=True)
cellphoneno = models.CharField(max_length=20, blank=True, null=True)
class Meta:
managed = False
db_table = 'MstrStoreHeadContact'
def get_absolute_url(self):
return reverse('masterdata:owner-contact-details', kwargs={'pk': self.contactid})
For me the code: return reverse('masterdata:owner-contact-details', kwargs={'pk': self.contactid} is supposed to take the control to the "details page" that will display the new record that has been added to the DB.
The problem
When the code above is executed, the variable self.contactid is set to 0. See below:
This results in the following URL to be placed in the address bar:
http://127.0.0.1:8000/masterdata/owner/0/contact/details
Because of the "0", this leads to a 404 error. In the DB, the value is set - for example to 10.
Again, the data saves to the DB JUST FINE- there is no problem with
this part. The problem lies with what happens AFTER the data is saved
to the DB.
Below are some entries from the urls.py file
from the urls.py file
url(r'^owner/(?P<pk>[0-9]+)/contact/details/$', views.MstrstoreheadcontactDetailsView.as_view(),
name='owner-contact-details'),
url(r'^owner/(?P<tenantid>[0-9]+)/contacts/add/$', views.MstrstoreheadcontactCreateView.as_view(),
name='owner-contact-add'),
from the views.py file
class MstrstoreheadcontactCreateView( CreateView ):
model = Mstrstoreheadcontact
fields = [ 'firstname', 'lastname', 'genderid', 'officephoneno', 'cellphoneno']
def form_valid(self, form):
contact = form.save(commit=False)
contact.tenantid = Mstrauthowner.objects.get(tenantid=self.kwargs['tenantid'])
return super(MstrstoreheadcontactCreateView, self).form_valid(form)
It seems like the code is not getting the data back from the DB properly (after the data has been saved). What can I do to fix the problem?
TIA

Well, thank goodness for debuggers. The following changes resolved all the problems for me :-)
views.py
class MstrstoreheadcontactCreateView( CreateView ):
model = Mstrstoreheadcontact
fields = [ 'firstname', 'lastname', 'genderid', 'officephoneno', 'cellphoneno']
def form_valid(self, form):
form.instance.tenantid = Mstrauthowner.objects.get(tenantid=self.kwargs['tenantid'])
return super(MstrstoreheadcontactCreateView, self).form_valid(form)
models.py
class Mstrstoreheadcontact(models.Model):
tenantid = models.ForeignKey('Mstrauthowner', models.DO_NOTHING, db_column='tenantid', blank=True, null=True)
contactid = models.BigIntegerField(primary_key=True, default=0)
[... snip ..]
def get_absolute_url(self):
[... snip ...]
return reverse('masterdata:owner-contact-details', kwargs={'pk': self.tenantid.pk})

Related

django import-export how to add foreign key

I am using django-import-export to import an excel to my model, what I do is that I create a form with some inputs from where it loads the file, then in form_valid() I process the file to load it to the database, the model has two foreign keys 'id_order' and 'gestion'; 'id_orden' comes in the excel and 'gestion' I get it with gestion= Gestion.objects.get(idgestion=obj.pk) which is the id of the form that I am saving, but what I want to know is how I can pass 'gestion' to ModelResource and then save it to the database
view.py
class GestionView(CreateView):
model = Gestion
form_class = GestionForm
template_name = 'asignacion/gestion.html'
success_url = reverse_lazy('asignacion_url:gestion')
def form_valid(self, form):
isvalid = super().form_valid(form)
obj = form.save()
gestion= Gestion.objects.get(idgestion=obj.pk)
file = self.request.FILES['file']
item_gestion =ItemResourceResource()
dataset = Dataset()
imported_data = dataset.load(file.read(), format='xls')
result = item_gestion.import_data(dataset, dry_run=True)
if not result.has_errors():
item_gestion.import_data(dataset, dry_run=False)
model.py
class ItemGestion(models.Model):
idgestion = models.AutoField(primary_key=True)
numero_imagenes = models.CharField(max_length=45, blank=True, null=True)
id_orden = models.ForeignKey('Asignacion', models.DO_NOTHING)
aviso_sap = models.CharField(max_length=45, blank=True, null=True)
poliza = models.CharField(max_length=45, blank=True, null=True)
observacion_cierre = models.CharField(max_length=250, blank=True, null=True)
gestion=models.ForeignKey('Gestion', models.DO_NOTHING)
resources.py
class ItemResourceResource(resources.ModelResource):
id_orden = fields.Field(column_name='id_orden', attribute='id_orden',
widget=ForeignKeyWidget(Asignacion,'id_orden'))
class Meta:
model = ItemGestion
import_id_fields = ('id_orden',)
exclude = ('idgestion', )
It is easy to do. You need to pass the gestion value into your Resource, and then link it to the instance before it is persisted:
class ItemResourceResource(ModelResource):
def __init__(self, gestion):
self.gestion = gestion
def before_save_instance(self, instance, using_transactions, dry_run):
instance.gestion = self.gestion
class Meta:
# ...
gestion = Gestion.objects.get(idgestion=obj.pk)
item_gestion = ItemResourceResource(gestion)
Obviously this means that all the instances created from the rows in your dataset will be linked to the same 'gestion' value.
btw import-export integrates with django-admin, so you can use the admin interface to import data rather than writing your own forms (if that fits your requirements). See the docs for more information.

How to solve url parameter problem in Django?

I have a strange problem.
I have a page that uses url parameters. Users can reach this site based on their project id and name and the group(csoport) name that stored in three models. This is a link for an example page:
/performance/monthlyfeedback/{{ request.user.profile.csoport }}
That link works fine if the name of the csoport is a number. If it is any kind of a text it gives me 404 error that I can't figure out why.
models.py
class Profile(models.Model):
def __str__(self):
return str(self.user)
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
csoport = models.CharField(max_length=100, null=True, blank=True)
class Projekt_perf(models.Model):
def __str__(self):
return str(self.projekt_perf)
projekt_perf = models.CharField(max_length=250)
jogosult_01_perf = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateField(auto_now_add=True, auto_now=False, blank=True)
class Performance_profile(models.Model):
def __str__(self):
return str(self.user_name)
user_name = models.ForeignKey(User, on_delete=models.CASCADE)
projekt_perf = models.ForeignKey(Projekt_perf,on_delete=models.CASCADE)
views.py
I am using raw query in the views.
def obj_results(request, projekt_perf_id, projekt_perf, user_name_id, csoport):
person = Projekt_perf.objects.raw('SELECT * FROM performance_projekt_perf INNER JOIN performance_performance_profile ON performance_projekt_perf.id = performance_performance_profile.projekt_perf_id INNER JOIN stressz_profile ON performance_performance_profile.user_name_id = stressz_profile.user_id WHERE performance_projekt_perf.id = %s AND projekt_perf = %s AND stressz_profile.user_name_id = %s AND stressz_profile.csoport = %s',[projekt_perf_id, projekt_perf, user_name_id, csoport])
context = {
'person': person,
}
return render(request, 'performance/obj-results.html', context)
urls.py
app_name = 'performance'
urlpatterns = [
path('monthlyfeedback/<int:projekt_perf_id>', login_required(views.Performance_test), name='performance_feedback'),
path('list/<int:projekt_perf_id>/<projekt_perf>', login_required(views.list), name='performance_list'),
path('obj-results/<int:projekt_perf_id>/<projekt_perf>/<int:user_name_id>/<csoport>', login_required(views.obj_results), name='obj_results'),
]
What am I doing wrong?
In urls.py:
path('monthlyfeedback/<int:projekt_perf_id>'
You have defined the “project_perf_id” as int. Change it.
Can you try with <str:csoport> but I reccomend you to use slugs.
path('obj-results/<int:projekt_perf_id>/<projekt_perf>/<int:user_name_id>/<str:csoport>', login_required(views.obj_results), name='obj_results'),

Django - ListView url not connecting to desired view

I am new to Django and have hit a wall with a certain part of my project and I hope someone can help.
I have two ListViews in my views.py file which I would like to work similar to published/draft posts (I'm actually using sanitised and unsanitised reports). Currently, every time I try to access the "Unsanitised" list view (unsanitised_list.html), it just directs me to the the sanitised list view (intelreport_list.html)
views.py:
class IntelReportListView(ListView):
model = IntelReport
context_object_name = 'all_logs'
def get_queryset(self):
return IntelReport.objects.filter(create_date__lte=timezone.now()).order_by('-create_date')
class UnsanitisedListView(LoginRequiredMixin, ListView):
login_url = '/login/'
redirect_field_name = 'intel_db/unsanitised_list.html'
model = IntelReport
def get_queryset(self):
return IntelReport.objects.filter(sanitised__isnull=True).order_by('-create_date')
models.py
class IntelReport(models.Model):
gpms_choices = (
***REDACTED***
)
gpms = models.CharField(max_length=20, blank=True, null=True, choices=gpms_choices)
officer = models.CharField(max_length=50)
create_date = models.DateTimeField(auto_now_add=True)
sanitised = models.BooleanField(default=False)
source_eval_choices = (
***REDACTED****
)
source_eval = models.CharField(max_length=50, blank=True, null=True, choices=source_eval_choices)
intel_eval_choices = (
***REDACTED***
)
intel_eval = models.CharField(max_length=100, blank=True, null=True, choices=intel_eval_choices)
report = models.TextField(max_length=5000, blank=True, null=True)
def sanitised_log(self):
self.sanitised = True
self.save()
def get_absolute_url(self):
return reverse('log_details', kwargs={'pk':self.pk})
def __str__(self):
return str(self.pk)
urls.py
from django.urls import path
from intel_db import views
urlpatterns = [
path('welcome/', views.AboutView.as_view(), name='about'),
path('logs/', views.IntelReportListView.as_view(), name='log_list'),
path('logs/<int:pk>/', views.IntelReportDetailView.as_view(), name='log_detail'),
path('logs/new_log/', views.IntelReportCreateView.as_view(), name='new_log'),
path('unsanitised/', views.UnsanitisedListView.as_view(), name='unsanitised'),
path('logs/<int:pk>/sanitise_log/', views.sanitsed_report, name='sanitised_report'),
]
and on my landing page (landing.html), this is the link I'm using to try and reach the unsanitised_list.html:
**<a href="{% url 'unsanitised' %}">**
I cannot figure out why it keeps redirecting me to intelreport_lists.html (the sanitised logs) rather than unsanitised_list.html (the unsanitised logs).
I hope I'm not just missing something really simple but I've been over it and tried to re-write it innumerable times and can't get it right.
I hope this is enough information and any help would be greatly appreciated.
Cheers
You just have to override template_name when you extend ListView. I mean update your IntelReportListView and UnsanitisedListViewlike this,
class IntelReportListView(ListView):
model = IntelReport
context_object_name = 'all_logs'
template_name = 'YOUR_APP_NAME/intelreport_list.html'
def get_queryset(self):
return IntelReport.objects.filter(create_date__lte=timezone.now()).order_by('-create_date')
class UnsanitisedListView(LoginRequiredMixin, ListView):
login_url = '/login/'
redirect_field_name = 'intel_db/unsanitised_list.html'
template_name = 'YOUR_APP_NAME/unsanitised_list.html'
model = IntelReport
def get_queryset(self):
return IntelReport.objects.filter(sanitised__isnull=True).order_by('-create_date')
If you are interested to find out why it was redirecting to intelreport_list.html rather than unsanitised_list.html, whenever you extend ListView it will look for MODEL_NAME_list.html by default, where MODEL_NAME is name of the model that you have used inside your list views (in lower case). Since you have used model = IntelReport inside UnsanitisedListView, it's redirecting to intelreport_lists.html

i have issues with while rendering dynamic data for templates

Code below models
class Events(models.Model):
event_author=models.ManyToManyField(Author)
event_title=models.CharField(max_length=300)
event_title_image = models.ImageField(upload_to='images/', blank=True, null=False)
event_description=models.TextField(blank = True)
event_image_description = models.ImageField(upload_to='images/', blank=True, null=True)
event_release_date = models.DateField(null="false")
def __str__(self):
return self.event_title
def publish(self):
self.event_release_date = timezone.now()
self.save()
views
def Event(request):
events=Events.objects.filter(published_date__lte=timezone.now()).order_by('event_title')
return render(request, 'polls/events.html', {})
templates
<p>Events page </p>
{{ events }}
Error
FieldError at /events
Cannot resolve keyword 'published_date' into field. Choices are: event_author, event_description, event_image_description, event_release_date, event_title, event_title_image, id
while I am running a server I got an error like filed error please help out of this i am new django.
That's because you're filtering on a field which not included on your model.
events=Events.objects.filter(published_date__lte=timezone.now()).order_by('event_title')
as I can see, your published_date is correspond to field event_release_date on your model, so it supposed to be like this:
events=Events.objects.filter(event_release_date__lte=timezone.now()).order_by('event_title')

django upload files (models and forms)

I work on a group project with django. I have a problem with file upload. It is an web app to create, share forms with some additional options (graphs, charts,....). I should mention that i am new to django (total beginner)
1.models.py:
class Form(TimeStampedModel, TitleSlugDescriptionModel):
author = models.ForeignKey(User,
on_delete=models.CASCADE)
title = models.CharField(max_length=512)
is_final = models.BooleanField(default=False)
is_public = models.BooleanField(default=False)
is_result_public = models.BooleanField(default=False)
image = models.ImageField(upload_to="upload_location", null=True,
blank=True, width_field="width_field",
height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
file = models.FileField(upload_to="upload location", null=True,
blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('form-detail', kwargs={'slug': self.slug})
2. forms.py:
class DocumentUpload(forms.ModelForm):
class Meta:
model = Form
field = ["image", "file"]
3. Certainly, i made a migration, changed main settings (urls, MEDIA_ROOT etc)
4. views.py THIS IS MY PROBLEM
I try to modified existing "create_form(request)" function.
In any tutorials we use "form = form from forms.py", In my project we use "form = model from models.py". How should I modify this this function to complete this upload files.
def create_form(request):
if request.method == 'POST':
user = request.user
data = ParseRequest(request.POST)
parsed_form = data.form()
parsed_questions = data.questions()
form = Form(request.FILES, author=user,
title=parsed_form['title'],
is_final=parsed_form['is_final'],
is_public=parsed_form['is_public'],
is_result_public=parsed_form['is_result_public'],
description=parsed_form['description'])
form.save()
for d in parsed_questions:
question = Question(request.FILES, form=form, question=d['question'])
question.save()
for opt in d['options']:
option = Option(question=question, option=opt)
option.save()
return render(request, 'forms/form_form.html', {})
I would appreciate any help, thx
i needed to use a form from forms.py and add additional field manually.
Thx

Categories

Resources