Django IntegrityError, get error number or code - python

I want to check for IntegrityError(1048, "Column 'ean' cannot be null").
What is the proper way to do this? I feel like I'm not using the best method.
Product class
class Product(models.Model):
ean = models.BigIntegerField()
name = models.CharField()
Currently I'm doing this crazy trick.
newProduct = Product(ean=None, name='Foo')
try:
newProduct.save()
except IntegrityError, e:
error = e
code = error.__getslice__(0,1)
code = error[0]
# handle error 1048
I would love to see a proper example of handling a specific IntegrityError in Python / Django.

I think the best solution is not to handle the IntegrityError but to validate the model instance before saving it:
# Run validation
try:
newProduct.full_clean()
except ValidationError as error:
error.error_dict # A dictionary mapping field names to lists of ValidationErrors.
error.message_dict # A dictionary mapping field names to lists of error messages.
# In your case you can check
for e in error.error_dict.get('ean'):
if e.code == 'blank':
# ean was empty

IntegrityError exception handling is little different ,So to fetch number.
e.args[0]
For more information : https://www.programcreek.com/python/example/5321/MySQLdb.IntegrityError

Field ean is an required field,you cannot pass None value into it.To fix this issue add
ean = models.BigIntegerField(null=True,blank=True)
Then it wont show integrity error.Becuase right now the field is expecting some data not null value.
Otherwise
newProduct = Product(ean=256, name='Foo')
pass an integer value.This worked for me.
You can also right some form validation to prevent this issue.
example:
def clean_ean(self):
data = self.cleaned_data['ean']
if "fred#example.com" not in data:
raise forms.ValidationError("message")
# Always return the cleaned data, whether you have changed it or
# not.
return data
Refer:https://docs.djangoproject.com/en/1.8/ref/forms/validation/

Django has some optional parameters for checking content of fields such as null and blank for checking that field is not empty, so has some validators that you can use for checking content of fields for example use django MinLengthValidator for checking length of ean field content:
from django.core.validators import MinLengthValidator
class Product(models.Model):
ean = models.BigIntegerField(null=False, validators=MinLengthValidator(1, message='The "ean" field min length is one char at least.'))
name = models.CharField()
By using MinLengthValidator you can return custom message if ean field is empty.

I made a method to validate the product object before saving it. This way I'm sure that I can save the product without running into errors. Thanks for the tips!
For more information see that Django documentation on validating objects.
class Product(model.Models):
def saveProduct(self, product):
if self.validateProduct(product):
product.save()
def validateProduct(self, product):
try:
product.full_clean()
except ValidationError:
return False
return True

You can try
ean = models.BigIntegerField(requried=True)
...
newP = Product(name='Foo')
This result may be what you want.

Related

Where is a django validator function's return value stored?

In my django app, this is my validator.py
from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
def validate_url(value):
url_validator = URLValidator()
url_invalid = False
try:
url_validator(value)
except:
url_invalid = True
try:
value = "http://"+value
url_validator(value)
url_invalid = False
except:
url_invalid = True
if url_invalid:
raise ValidationError("Invalid Data for this field")
return value
which is used to validate this :
from django import forms
from .validators import validate_url
class SubmitUrlForm(forms.Form):
url = forms.CharField(label="Submit URL",validators=[validate_url])
When I enter URL like google.co.in, and print the value right before returning it from validate_url, it prints http://google.co.in but when I try to get the cleaned_data['url'] in my views, it still shows google.co.in. So where does the value returned by my validator go and do I need to explicitly edit the clean() functions to change the url field value??
The doc says the following:
The clean() method on a Field subclass is responsible for running to_python(), validate(), and run_validators() in the correct order and propagating their errors. If, at any time, any of the methods raise ValidationError, the validation stops and that error is raised. This method returns the clean data, which is then inserted into the cleaned_data dictionary of the form.
I am still not sure where the validator return value goes and if it is possible to change cleaned_data dict using the validator.
From the docs:
A validator is merely a callable object or function that takes a value
and simply returns nothing if the value is valid or raises a
ValidationError if not.
The return value is simply ignored.
If you want to be able to modify the value you may use clean_field on the forms as described here:
class SubmitUrlForm(forms.Form):
url = ...
def clean_url(self):
value = self.cleaned_data['url']
...
return updated_value
Validators are only about validating the data, hence that is why the return value of the validator gets ignored.
You are looking for data "cleaning" (transforming it in a common form). In Django, Forms are responsible for data cleaning.
Use URLField. It validates value and prepends http if neccessary.

Confuse for using get queryset and using pass to ignore an exception and proceed in my django view

I wrote a view to update my draft object , before updating my draft I need to see if any draft exists for package(draft.package) in db or not .
If any draft available, i need to update that draft's fields.
I am using get queryset to look into db to check draft availability.
I want to know that using get queryset here is good way or not and using pass into except.
My View
def save_draft(draft, document_list):
"""
"""
try:
draft = Draft.objects.get(package=draft.package)
except Draft.DoesNotExist as exc:
pass
except Draft.MultipleObjectsReturned as exc:
raise CustomException
else:
draft.draft_document_list.filter().delete()
draft.draft_document_list.add(*document_list)
draft.save()
Extra Information :
models.py
class Package(models.Model):
name = models.CharField(max_length=100)
# -- fields
class Document(models.Model):
# -- fields
Class Draft(models.Model):
# --- fields
package = models.ForeignKey(Package)
draft_document_list = models.ManyToManyField(Document)
My Algorithm :
# first check to see if draft exists for package
# if exists
# overwrite draft_document_list with existed draft and save
# if none exists
# update passed draft object with draft_document_list
Input variables
save_draft(draft, document_list)
draft --> latest draft object
document_list --> list of documents mapped with Draft as M2M.
Yes, for for you models and method signature you use get right. To simplify things you can get rid of delete()/add() methods by direct assign document_list to M2M relation.
def save_draft(draft, document_list):
try:
draft = Draft.objects.get(package=draft.package)
except Draft.DoesNotExist:
pass
except Draft.MultipleObjectsReturned:
raise CustomException
draft.draft_document_list = document_list
draft.save()
EDIT: If there can be only one draft per package then why you use ForeignKey(Package)? With OneToOne relation your code will be much simpler:
def save_draft(draft, document_list):
draft.draft_document_list = document_list
draft.save()

How to change the name of the document=True field of Haystack in Django?

I want to use haystack, but all my models have "body" as their text-field name. it is the same on all models though.
Now I get this error:
All 'SearchIndex' classes must use the same 'text' fieldname for the 'document=True' field. Offending index is '<qna.search_indexes.QuestionIndex object at 0x2435328>'.
That's the index file:
import datetime
from haystack import indexes
from qna.models import Question
class QuestionIndex(indexes.SearchIndex, indexes.Indexable):
subject = indexes.CharField(document=False, use_template=False)
body = indexes.CharField(document=True, use_template=True, model_attr='user')
pub_date = indexes.DateTimeField(model_attr='pub_date')
def get_model(self):
return Question
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.filter(pub_date__lte=datetime.datetime.now())
It is the ONLY one! With what is it offending? As far as I understand the field name doesn't have to be "text" it only has to be the same on every field. But it's the only field! Do I have to change some config? What might be the cause of this... ??
I saw your error in the haystack source. It looks like there is a setting for the name of this field (https://github.com/toastdriven/django-haystack/blob/master/haystack/utils/loading.py#L154):
self.document_field = getattr(settings, 'HAYSTACK_DOCUMENT_FIELD', 'text')
Later in that file (https://github.com/toastdriven/django-haystack/blob/master/haystack/utils/loading.py#L222) it checks to make sure that your index name matches and blows up with the error you saw if they don't agree:
if field_object.index_fieldname != self.document_field:
raise SearchFieldError("All 'SearchIndex' classes must use the same '%s' fieldname for the 'document=True' field. Offending index is '%s'." % (self.document_field, index))
If you set HAYSTACK_DOCUMENT_FIELD to "body" in your settings, it looks like that should do it.

Django_tables2: Dynamically hiding columns based on the request

I have a table that's based on a model that has several fields. I also have two TemplateColumns, one for editing the specific entity and another for deleting it. Here is my code:
class EntitetTable(tables.Table):
edit = tables.TemplateColumn(template_name='azuriranje/izmena.html',
orderable=False, visible=False)
delete = tables.TemplateColumn(template_name='azuriranje/brisanje.html',
orderable=False, visible=False)
class Meta:
abstract = True
attrs = {'class': 'paleblue', }
class TipPredmetaTable(EntitetTable):
class Meta(EntitetTable.Meta):
model = models.TipPredmeta
Now, I have a user hierarchy in my system and only users that are bookkeepers can edit and delete the data. That being said, I tried to implement a check in my view to hide the two TemplateColumns:
#login_required
def tippredmeta(request):
try:
korisnik = request.user.radnik
except ObjectDoesNotExist:
return HttpResponseRedirect("/main/")
queryset = TipPredmeta.objects.all()
table = TipPredmetaTable(queryset)
if korisnik.is_kustos:
table.edit.visible = True
table.delete.visible = True
RequestConfig(request).configure(table)
return render_to_response('azuriranje/tabelaPrikaz.html', {'table': table, },
context_instance=RequestContext(request))
However, I get the following exception on the table.edit.visible = True line:
Exception Type: AttributeError
Exception Value: 'TipPredmetaTable' object has no attribute 'edit'
Now, here are the things I've tried:
- First I thought about using fields and exclude, but I couldn't alter that dynamically.
- Then I thought about placing all of this into the __init__ method, effectively making edit and delete attributes of my EntitetTabel (the idea was to solve the error) but while the error was gone, so were my TemplateColumns. I tried displaying them via fields, but that didn't help. My guess is that the superclass, the tables.Table, doesn't work like that.
You can use the exclude attribute of the tables.Table for excluding unwanted fields. It also works after creating the table instance. So in your case, you can do something like this.
First leave your columns visible (i removed the visible=False):
class EntitetTable(tables.Table):
edit = tables.TemplateColumn(template_name='azuriranje/izmena.html',
orderable=False)
delete = tables.TemplateColumn(template_name='azuriranje/brisanje.html',
orderable=False)
Then based on your condition, you can exclude the edit and delete fields:
table = TipPredmetaTable(queryset)
if not korisnik.is_kustos:
table.exclude = ('edit', 'delete',)

ForeignKey model has no Manager (i.e., 'Foo' object has no attribute 'foo_set')

I have searched around for an answer to this but can't find one. When using a ForeignKey, I am consistently getting an error telling me that 'Foo object has no attribute 'foo_set'. I am a bit new to Django/Python, so I'm sure there is a simple answer here, but I haven't been able to find it so far. Here's some code (to store varied Boards for use in a game, each of which should have a number of Hexes associated with it):
Models:
class Boards(models.Model):
boardnum = models.IntegerField(unique=True)
boardsize = models.IntegerField(default=11)
hexside = models.IntegerField(default=25)
datecreated = models.DateTimeField(auto_now_add = True)
class Hexes(models.Model):
boardnum = models.ForeignKey(Boards, null = True)
col = models.IntegerField()
row = models.IntegerField()
cost = models.IntegerField(default=1)
Code (this works):
newboard, createb = Boards.objects.get_or_create(boardnum=boardn)
createb returns True.
Code (this immediately follows the above, and does not work):
try:
hx = newboard.boards_set.create(col=c, row=r)
except Exception, err:
print "error:", err
traceback.print_exc()
Both "err" and "traceback.print_exc()" give: AttributeError: 'Boards' object has no attribute 'boards_set'
I get the same error if I first create the Hexes record with a get_or_create and then try a newboard.boards_set.add() on it.
Any ideas? All suggestions appreciated.
The name that Django uses for a reverse foreign key manager is the name of the model that contains the foreign key, not the name of the model that the manager is on.
In your case, it will be:
newboard.hexes_set.create(col=c,row=r)
I find it useful to use the manage.py shell command to import your models and inspect them (with dir, etc) to check out all the available attributes.

Categories

Resources