I have created a basic setup for autocomplete-light on one of my forms. I am using direct SQL queries to access the data I require, and the Select2ListView to send the data to the template. The autocomplete data is available on the browser, but it is case sensitive. Can someone please suggest what I can do to make the autocomplete-light become case insensitive?
I read about using 'split_words = True' from the AutocompleteModel class, but I have no idea how to do this.
For example (q = 'ger'):
Command Prompt (views.py print statement) returns
['Algeria', 'Germany', 'Niger (the), 'Nigeria']
http://127.0.0.1:8000/autocomplete/country-autocomplete?q=ger returns
{"results": [{"text": "Algeria", "id": "Algeria"}, {"text": "Niger (the)", "id": "Niger (the)"}, {"text": "Nigeria", "id": "Nigeria"}]}
As you can see, Germany is visible in the data I am returning from the view, but there is some additional filtering going on by autocomplete-light. I need to change autocomplete-light so that the filtering it performs is case-insensitive. Any ideas?
I am running Python 3.5.2, and the latest pip install for autocomplete-light.
Thanks
Stephen
View
class CountryAutocomplete(autocomplete.Select2ListView):
def get_list(self):
# Only allow authenticated users
if not self.request.user.is_authenticated():
return []
# Read all country names from database
cursor = connection.cursor()
cursor.execute('SELECT country_name FROM autocomplete_iso3166;')
results = cursor.fetchall()
# Flatten database query into a list
results = [e for l in results for e in l]
# Check POST query and filter further
if self.q:
# Make query case insensitive
results = list(filter(lambda k: self.q.casefold() in str(k).casefold(), results))
print(results)
return results
Form
class VendorForm(forms.ModelForm):
class Meta:
model = client
fields = [
'vendor_name', 'address5', 'address4', 'address3', 'address2', 'address1',
]
widgets = {
'address5': autocomplete.ListSelect2(url='country-autocomplete'),
'address4': autocomplete.ListSelect2(url='state-autocomplete',forward=['address5'])
}
Model
class client(models.Model):
vendor_name = models.CharField(max_length=100)
user_admin = models.ForeignKey(User, unique=False, null=True, blank=True)
address1 = models.CharField(null=True, blank=True, max_length=200)
address2 = models.CharField(null=True, blank=True, max_length=50)
address3 = models.CharField(null=True, blank=True, max_length=50)
address4 = models.CharField(null=True, blank=True, max_length=50)
address5 = models.CharField(null=True, blank=True, max_length=50)
if self.q:
queryset = queryset.filter(country_name__istartswith=self.q)
i means case insensitive. This example uses the beginning of the field.
If you want an exact match case-insensitive it would be:
country_name__iexact=self.q
Related
someone can help me?
I am creating a website for my church with django with an extension menu that will represent all church extensions worldwide. my problem is that i want a system that will show the user churches near him or in his area. put a text box to ask for his current address and show him all the parishes near him and their locations. except that the extensions are classified as follows: country > Province > city > Commune > district > parish
at my first reflection I tried to create the following models
from django.db import models
# Create your models here.
class Pays(models.Model):
Ctn = (
('Africa', 'Africa'),
('America','America'),
('Asia','Asia'),
('Europe','Europe'),
)
STATUS = (
('True', 'True'),
('False','False'),
)
name=models.CharField(max_length=100)
continent=models.CharField(max_length=50, default="Afrique")
slug=models.SlugField()
date_created=models.DateTimeField(auto_now_add=True)
status=models.CharField( choices=STATUS, max_length=100)
def __str__(self):
return self.name
class Church(models.Model):
STATUT = (
('En Service', 'En Service'),
('Fermée','Fermée'),
)
CAT = (
('Siège', 'Siège'),
('Eglise centrale', 'Eglise centrale'),
('Eglise locale','Eglise locale'),
)
name=models.CharField(max_length=100)
address=models.CharField(max_length=255)
Town=models.CharField(max_length=150)
Contry=models.ForeignKey(Pays,on_delete=models.CASCADE )
description=models.CharField(max_length=255)
effectif=models.IntegerField()
slug=models.SlugField()
date_created=models.DateTimeField(auto_now_add=True)
statut=models.CharField(choices=STATUT,max_length=100)
category=models.CharField(choices=CAT,max_length=100)
def __str__(self):
return self.name
but the problem is when I want to display a parish which is in a district of a municipality of a city of a province of a country of a determined continent example: continent= africa, country=DRC (democratic republic of congo), province= Kantanga, city=Lubumbashi, commune=rwashi and parish=bel'air 1.
I can't manage to build a django query that will return the parish to me in this order that I just showed above
Why does the following code give me an error when trying to write to a SQL Server but not on sqlite3 or mysql?
obj, created = cls.objects.using(database_data).update_or_create(**item)
The datamodel is defined below:
class fubar(models.Model)
region = models.CharField(max_length=32, default='ABCD')
market_participant = models.CharField(max_length=32, default='ACME')
trade_date = models.DateField()
interval_begin = models.DateTimeField()
interval_end = models.DateTimeField()
interval_type = models.CharField(max_length=32, default='5MIN')
location = models.CharField(max_length=32, default=None, null=True, blank=True)
location_type = models.CharField(max_length=32, default=None)
class Meta:
unique_together = [
'region',
'market_participant',
'trade_date',
'interval_begin',
'interval_end',
'interval_type',
'location',
'location_type'
]
IntegrityError: (
'23000',
"[23000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]
Cannot insert duplicate key row in object 'dbo.foo`
with unique index 'foo_region_market_participant_trade_date_interval_begin_inte_d7d3bf7e_uniq'.
The duplicate key value is
(ABCD, ACME, 2020-12-06, 2020-12-06 00:00:00.0000000, 2020-12-06 00:05:00.0000000, 5MIN, BAZ, QUX).
(2601)
(SQLExecDirectW)"
)
Note: Error code was originally one line. I have re-formatted for readability.
I'v been banging my head over this for 2 days straight and i still can understand/find a way to do this and it looks super simple but im obviously overlooking something (also im fairly new to DBs :) ).
I want to have Owner and Pet model.
Pets have 'owner ids' as foreign keys, and Owners have 'pets' as relationship, so far so good.
But now i also want Owners to have one 'pet id' written as 'favorite pet'.
Having foreign keys in both models (each others keys) started to make bunch of different problems (different depending on how i try to solve it, but either circular dependency or some multipath error)
I also noticed that if i avoid having 'favourite_pet_id'-foreign key in Owner model, keeping only favourite_pet-relationship, then i dont have this written anywhere in DB (at least not visible), it exists only as 'relationship' ?
What would be correct way of doing this ?
Thanks in advance !
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Owner(db.Model):
id = db.Column(db.Integer, primary_key=True)
pets = db.relationship('Pet', foreign_keys='Pet.owner_id')
favourite_id = db.Column(db.Integer, db.ForeignKey('pet.id'))
favourite = db.relationship('Pet', uselist=False, foreign_keys='Owner.favourite_id')
class Pet(db.Model):
id =db.Column(db.Integer, primary_key=True)
owner_id = db.Column(db.Integer, db.ForeignKey('owner.id'))
owner = db.relationship('Owner', uselist=False, back_populates='pets', foreign_keys='Pet.owner_id')
o = Owner() # one owner
p1 = Pet() # pet 1
p2 = Pet() # pet 2
p1.owner=o # setting owner for pet1
p2.owner=o # setting owner for pet2
o.favourite=p2 # setting pet2 to be favourite
#db.session.add(o)
#db.session.add(p1)
#db.session.add(p2)
#db.session.commit()
print (p1.owner) # owner
print (p2.owner) # owner
print (p1) # pet 1
print (p2) # pet 2
print (o.pets) # owners pets
print (o.favourite) # favourite pet
Here's a working version of your code below. The key is being more explicit about the relationship (e.g. join condition) as there are multiple relationships between the models/tables.
Note: While not part of your question/request, I also reformatted a bit for PEP8 conformity and readability. The later is a good practice to adopt early on as model files typically grow quickly and can become very difficult to read, digest, and debug.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Owner(db.Model):
id = db.Column(
db.Integer,
primary_key=True,
)
favourite_pet_id = db.Column(
db.Integer,
db.ForeignKey('pet.id'),
nullable=True,
)
favourite_pet = db.relationship(
'Pet',
uselist=False,
foreign_keys=[favourite_pet_id],
primaryjoin='Pet.owner_id == Owner.favourite_pet_id',
)
class Pet(db.Model):
id = db.Column(
db.Integer,
primary_key=True,
)
owner_id = db.Column(
db.Integer,
db.ForeignKey('owner.id'),
)
owner = db.relationship(
'Owner',
uselist=False,
foreign_keys=[owner_id],
primaryjoin='Pet.owner_id == Owner.id',
backref=db.backref(
'pets',
uselist=True,
),
)
db.create_all()
o = Owner() # one owner
p1 = Pet() # pet 1
p2 = Pet() # pet 2
p1.owner = o # setting owner for pet1
p2.owner = o # setting owner for pet2
o.favourite_pet = p2 # setting pet2 to be favourite
print(p1.owner) # owner
print(p2.owner) # owner
print(p1) # pet 1
print(p2) # pet 2
print(o.pets) # owners pets
print(o.favourite) # favourite pet
I'm learning Django and I'm trying to make a Cart, which the customer can get and item and add it in his/her order row and then the order will be submitted. so my teacher said use def initiate(customer), and I don't understand how to use it. Can someone please explain it to me? Thank you.
here is the code I'm working on it:
User = get_user_model()
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=Product, related_name="User")
phone = models.CharField(max_length=20)
address = models.TextField()
balance = models.IntegerField(default=20000)
def deposit(self, amount):
self.balance += amount
self.save()
def spend(self, amount):
if amount > self.balance:
raise ValueError
self.balance -= amount
self.save()
class OrderRow(models.Model):
product = models.ManyToManyField(Product)
order = models.ForeignKey('Order', on_delete=models.CASCADE)
amount = models.IntegerField()
class Order(models.Model):
# Status values. DO NOT EDIT
STATUS_SHOPPING = 1
STATUS_SUBMITTED = 2
STATUS_CANCELED = 3
STATUS_SENT = 4
customer = models.ForeignKey('Customer', on_delete=models.SET_NULL)
order_time = models.DateTimeField(auto_now=True)
total_price = Sum(F('amount') * F('product__price'))
status = models.IntegerField(choices=status_choices)
#staticmethod
def initiate(customer):
Order.initiate(User)
def add_product(self, product, amount):
Order.status = 1
OrderRow.product = Product.objects.get(id=product.id)
print(product.id)
if OrderRow.objects.filter(product=product).exists():
preexisting_order = OrderRow.objects.get(product=product, order=self)
preexisting_order.amount += 1
preexisting_order.save()
else:
new_order = OrderRow.objects.create(
product=product,
cart=self,
amount=1,
)
new_order.save()
You are probably supposed to create a new Order associated with this customer. Something along the following lines:
#classmethod
def initiate(cls, customer):
return cls.objects.create(customer=customer, status=cls.STATUS_SHOPPING)
There are some other issues with your code. You cannot use SET_NULL if the fk is not nullable:
customer = models.ForeignKey('Customer', on_delete=models.SET_NULL, null=true)
There should not be multiple products per row:
class OrderRow(models.Model):
product = models.ForeignKey(Product) # not many2many!
# ...
Also, your add_product needs quite some fixing:
def add_product(self, product, amount):
self.status = self.STATUS_SHOPPING # the instance is self + use your descriptive variables
print(product.id)
# filter only rows in the current order!
if self.orderrow_set.filter(product=product).exists():
# fix naming: this is a row, not an order
preexisting_order_row = self.orderrow_set.get(product=product)
preexisting_order_row.amount += amount # why +1, you are adding amount
preexisting_order_row.save()
else:
new_order_row = OrderRow.objects.create(
product=product,
order=self,
amount=amount,
) # create saves already
I am getting this traceback;
--- Trimmed parts ---
File "C:\Users\muhammed\Desktop\gifdatabase\gifdatabase.py", line 76, in maketransaction
gif.tags = list(set(gif.tags + tags))
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\ndb\model.py", line 2893, in __hash__
raise TypeError('Model is not immutable')
TypeError: Model is not immutable
Here is related parts of my code;
class Gif(ndb.Model):
author = ndb.UserProperty()
#tags = ndb.StringProperty(repeated=True)
tags = ndb.KeyProperty(repeated=True)
#classmethod
def get_by_tag(cls,tag_name):
return cls.query(cls.tags == ndb.Key(Tag, tag_name)).fetch()
class Tag(ndb.Model):
gif_count = ndb.IntegerProperty()
class PostGif(webapp2.RequestHandler):
def post(self):
user = users.get_current_user()
if user is None:
self.redirect(users.create_login_url("/static/submit.html"))
return
link = self.request.get('gif_link')
tag_names = shlex.split(self.request.get('tags').lower())
#ndb.transactional(xg=True)
def maketransaction():
tags = [Tag.get_or_insert(tag_name) for tag_name in tag_names]
gif = Gif.get_or_insert(link)
if not gif.author: # first time submission
gif.author = user
gif.tags = list(set(gif.tags + tags))
gif.put()
for tag in tags:
tag.gif_count += 1
tag.put()
if validate_link(link) and tag_names:
maketransaction()
self.redirect('/static/submit_successful.html')
else:
self.redirect('/static/submit_fail.html')
What is the problem with gif.tags = list(set(gif.tags + tags)) line?
You are inserting tags instead of keys, you need to access
tags = [Tag.get_or_insert(tag_name).key .....]
but you can also make this a single network hop like this
futures = [Tag.get_or_insert_async(tag_name) for tag_name in tag_names]
futures.append(Gif.get_or_insert_async(link))
ndb.Future.wait_all(futures)
gif = futures.pop().get_result()
tags = [future.get_result() for future in futures]
but that's not really the question just a suggestion ^, for clearer answer with .key is
gif.tags = gif.tags + [tag.key for tag in tags]
# or
gif.tags.extend([tag.key for tag in tags])