GraphQL "There is no current event loop in thread 'Thread-2'." - django

I'm trying to get a list of tour reservations to a certain place using variables and I'm getting the error stated in the title
query GetReservationByTour($tour_place: String!) {
reservationsByPlace(place: $tour_place) {
id
tour {
id
place
}
}
}
Query:
class Query(graphene.ObjectType):
prices = graphene.List(PriceType)
tours = graphene.List(TourType)
users = graphene.List(UserType)
reservations = graphene.List(ReservationType)
reservations_by_place = graphene.Field(graphene.List(ReservationType), place=String(required=True))
def resolve_prices(root, info, **kwargs):
return Price.objects.all()
def resolve_tours(root, info, **kwargs):
return Tour.objects.all()
def resolve_users(root, info, **kwargs):
return User.objects.all()
def resolve_reservations(root, info, **kwargs):
return Reservation.objects.all()
def resolve_reservations_by_place(root, info, place, **kwargs):
return Reservation.objects.get(place=place)

It would be helpful to show the typeDef for the reservations query to see how it is defined.
However even without it your syntax should be:
query GetReservationByTour($tour_place: String!) {
reservations(place: $tour_place) {
id
tour {
id
place
}
}
}
because tour is a field in the return object from the reservations query and not an actual query (you can't nest queries). The arguments to the query ('place') are available to all the field resolvers so your resolve_tours resolver will be able to pick off the place even when it's nested within a reservation query.

Related

How to render the values without writing the logic in every view, Django?

In my view I want to request data from database, and on other page I also need this information, but I don't want to write this request logic again.
views.py
def account(request):
user_id = request.user.id
balance = Customer.objects.filter(name_id=user_id).values("usd").first()
bonus = Customer.objects.filter(name_id=user_id).values("bonus").first()
context1 = {'usd':balance['usd'],
'bonus':bonus['bonus'],
return render(request, 'account.html', context1)
def main(request):
(here I also need to request balance and bonus)
In def main(request): and on other pages I also need balance and bonus, but I don't really want to request this values in every view.
Can I somehow write it somewhere once and to render on pages, and do not write it in every view??
First of all, I don't think that doing query of the same Customer model twice for balance and for bonus is more efficient than query Customer instance and access its attributes as customer.balance/customer.bonus.
Nevertheless, there are two main options to make this code reusable:
Put it in the function
def get_balance_and_bonus(request):
customer = Customer.objects.filter(name_id=request.user.id).first()
return customer.balance, customer.bonus
And use it in view as:
balance, bonus = get_balance_and_bonus(request)
Second (more sophisticated) method is to make a decorator for all views that require the customer.
Decorator to deduce customer:
def add_customer(func):
def wrap(*args, **kwargs):
request = args[0]
user_id = request.user.id
kwargs['customer'] = Customer.objects.filter(name_id=user_id).first()
return func(*args, **kwargs)
return wrap
Then add it to all functions that need customer (Note that view in this case must have the respective argument in it)
#add_customer
def account(request, customer):
context1 = {'usd': customer.balance,
'bonus': customer. bonus,
return render(request, 'account.html', context1)
#add_customer
def main(request, customer):
# here customer.balance and customer.bonus are available

DoesNotExist - matching query does not exist

I have this django class-based view where i am trying to overwrite the get_queryset function because i want get to the inserted values from the frontend to search in my database after the subject with that name and then get the id. but when i call the view it gives me a "Subject matching query does not exist." because the subject_val is None. That makes sense because the user has not submitted the values jet.. so how do i get it to wait until a user have choosen "submit
class AttendanceList(LoginRequiredMixin, ListView):
model = AttendanceLog
template_name = "./attendancecode/showattendance.html"
def get_queryset(self):
class_val = self.request.GET.get('class')
subject_val = self.request.GET.get('subject')
sub = Subject.objects.get(name=subject_val).id
new_context = get_statstic(class_val, sub)
return new_context
def get_context_data(self, **kwargs):
context = super(AttendanceList, self).get_context_data(**kwargs)
context['class'] = self.request.GET.get('class')
context['subject'] = self.request.GET.get('subject')
return context
You can check if the values are not None, in case they are, you need to return another queryset of AttendanceLogs (for example AttendanceLog.objects.all() or AttendanceLog.objects.none()):
class AttendanceList(LoginRequiredMixin, ListView):
model = AttendanceLog
template_name = "./attendancecode/showattendance.html"
def get_queryset(self):
class_val = self.request.GET.get('class')
subject_val = self.request.GET.get('subject')
if class_val is not None and subject_val is not None:
sub = Subject.objects.get(name=subject_val).id
return get_statstic(class_val, sub)
# return another queryset:
return AttendanceLog.objects.none()
# …

How do we call a function each time an api end-point is called in django

In my Django server, there is an rest api through which we are saving the values in the database. If the name exists in the database then I update the value or else will create a new value and name. The code for the function is given below:
def getIgnitionData():
name_list =[]
value_list =[]
cursor = connections['ignition'].cursor()
cursor.execute('SELECT * FROM MDA_table')
value = cursor.fetchall()
cursor.execute('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = \'MDA_table\'')
name = cursor.fetchall()
for i in name:
name_list.append(str(i[0]))
for row in value:
for j in row:
value_list.append(str(j))
cursor.close()
print name_list
print value
#Here we will check to see if the variable exists. If so, update the value. If not,
#then create a new variable.
for k in range(0,len(name_list)):
if (Ignition.objects.filter(name = name_list[k]).exists()):
Ignition.objects.filter(name=name_list[k]).update(value = value_list[k])
else:
Ignition.objects.create(name=name_list[k], value=value_list[k])
The view_api.py is as follows:
class IgnitionViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows to view variables from the ignition database.
"""
serializer_class = IgnitionSerializer
#queryset = ignition.objects.all()
permission_classes = [HasGroupPermission]
required_groups = {
'GET': ['Admin', 'Facility', 'Operator'],
'PUT': [],
'POST': [],
}
ignition.getIgnitionData() # This is where we are calling the function
def get_queryset(self):
return Ignition.objects.all()
The code works well when I run the get request for the first time from the browser, but then if I update the values in the database without restarting the server then it doesn't even print the name_list (which means it doesn't call the code). If I restart the server and access the end point, then it does fetch the updated values. This is not practical though.
I wanted that whenever I call the api endpoint it fetches the updated values from the database so that I don't have to restart the server every time. Thanks in advance.
You can override dispatch() method which is calling each time your view is using:
class IgnitionViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows to view variables from the ignition database.
"""
serializer_class = IgnitionSerializer
#queryset = ignition.objects.all()
permission_classes = [HasGroupPermission]
required_groups = {
'GET': ['Admin', 'Facility', 'Operator'],
'PUT': [],
'POST': [],
}
def dispatch(self, request, *args, **kwargs):
ignition.getIgnitionData() # This is where we are calling the function
return super(IgnitionViewSet, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
return Ignition.objects.all()

django request.GET in models

Is it possible in Django to have models method with request.GET ?
e.g.
class Car(models.Model):
owner = ForeignKey(Owner)
car_model = ...
def car_filter(self, request):
query = request.GET.get("q")
if query:
Car.objects.filter(owner = self.id.order_by('id')
else:
Car.objects.filter(owner = me).order_by('id'
)
?
Purely technically speaking, sure, you can - as long as you can pass the request object from the view. The example code you've posted is syntactically incorrect, but, something like this is technically possible. You just have to make sure that the method is class-method, not instance-method one (since you don't have any instances in this case):
class Car(models.Model):
...
#classmethod
def get_by_owner(cls, request):
query = request.GET.get("q")
if query:
return cls.objects.filter(owner=query)
elif request.user.is_authenticated():
return cls.objects.all()
def your_view(request):
cars = Car.get_by_owner(request)
...
However, DON'T DO THIS. It's a bad idea because you're moving your request processing logic to a model. Models should only care about the data, and user request handling is view's job.
So, I'd suggest to have all the logic in the views:
def your_view(request):
cars = Car.objects.all().order_by("id")
query = request.GET.get("q")
if query:
cars = cars.filter(owner=query)
...
If you need some complicated logic, that a lot of views would share, you can use model managers:
class CarManager(model.Manager):
def owned(self, username=None):
queryset = super(CarManager, self).get_query_set()
if username:
user = Owner.objects.get(username=username)
queryset = queryset.filter(owner=user)
return queryset
class Car(models.Model):
...
objects = CarManager()
...
def your_view(request):
query = request.GET.get("q")
cars = Car.objects.owned(query)
...
Possible, but you have to pass the request manually:
# inside your views
qs_ = car_object.car_filter(request)
but I dont see any sense in doing so.
Everything that has to do with request should go into views which is the place for request-response flow.
Actually you can handle this stuff in your view only
def yourview(self, request):
query = request.GET.get("q")
if query:
Car.objects.filter(owner = self.id).order_by('id')
else:
Car.objects.filter(owner = me).order_by('id')
else other wise you have to send your request object to the model function from your view.

Filter django query set by a non-database operation

Working with ReviewBoard 1.6.11, which uses Django 1.3.3.
There is a RepositoryManager class that has a method called 'accessible', defined as this:
class RepositoryManager(Manager):
def accessible(self, user, visible_only=True, local_site=None):
"""Returns repositories that are accessible by the given user."""
if user.is_superuser:
qs = self.all()
else:
q = Q(public=True)
if visible_only:
q = q & Q(visible=True)
if user.is_authenticated():
q = q | (Q(users__pk=user.pk) |
Q(review_groups__users=user.pk))
qs = self.filter(q).distinct()
return qs.filter(local_site=local_site)
The problem is that I want to filter the results of this query by something else that does not interact with the database (filesystem permissions of the user). accessible() needs to return a QuerySet, though. Otherwise, I would just create a list and populate it with the appropriate items from the result.
I'm fairly new to Django. Is this a reasonable thing to do, or am I going about this all wrong?
I was able to solve this by creating a QuerySet subclass like so:
class RepositoryQuerySet(QuerySet):
def __init__(self, *args, **kwargs):
super(RepositoryQuerySet, self).__init__(*args, **kwargs)
self._user_filter = None
def _clone(self, *args, **kwargs):
retval = super(RepositoryQuerySet, self)._clone(*args, **kwargs)
retval._user_filter = self._user_filter
return retval
def filter_by_user_access(self, user):
self._user_filter = user.username
def iterator(self):
for repo in super(RepositoryQuerySet, self).iterator():
if self._user_filter is None:
yield repo
continue
# ...logic for restricting access by user...
# If user has access, just yield repo. If not, just 'continue'
Then in RepositoryManager.accessible, right after the call to distinct(), call:
qs.filter_by_user_access(user)
Finally, for the manager to use the new query set class, create:
def get_query_set(self):
return RepositoryQuerySet(self.model, using=self.db)
in the RepositoryManager class.