1

I can use this code to detect if the user is in America

ip, is_routable = get_client_ip(request)
ip2 = requests.get('http://ip.42.pl/raw').text

if ip == "127.0.0.1":
    ip = ip2

Country = DbIpCity.get(ip, api_key='free').country

widgets.py

If the user is American I want to pass information to the template bootstrap_datetimepicker.html.

I am really unsure how to add information about the users country to the below code (which I got from another website).

class BootstrapDateTimePickerInput(DateTimeInput):
    template_name = 'widgets/bootstrap_datetimepicker.html'

    def get_context(self, name, value, attrs):
        datetimepicker_id = 'datetimepicker_{name}'.format(name=name)
        if attrs is None:
            attrs = dict()
        attrs['data-target'] = '#{id}'.format(id=datetimepicker_id)
        # attrs['data-target'] = '#{id}'.format(id=datetimepicker_id)

        attrs['class'] = 'form-control datetimepicker-input'
        context = super().get_context(name, value, attrs)
        context['widget']['datetimepicker_id'] = datetimepicker_id
        return context

bootstrap_datetimepicker.html

I want to run a different JQuery function for American users.

{% if America %}  
<script>
  $(function () {
    $("#{{ widget.datetimepicker_id }}").datetimepicker({
      // format: 'DD/MM/YYYY/YYYY HH:mm:ss',


      format: 'MM/DD/YYYY',
      changeYear: true,
      changeMonth: false,
      minDate: new Date("01/01/2015 00:00:00"),
    });
  });
</script>




{% else %}


<script>
  $(function () {
    $("#{{ widget.datetimepicker_id }}").datetimepicker({
      // format: 'DD/MM/YYYY/YYYY HH:mm:ss',


      format: 'DD/MM/YYYY',
      changeYear: true,
      changeMonth: false,
      minDate: new Date("01/01/2015 00:00:00"),
   });
  });
</script>
{% endif %}
  
Ross Symonds
  • 404
  • 3
  • 15

1 Answers1

1

You can use Python package geoip2 to determine the location of the user (click on these two links for instructions on installing geoip2, get-visitor-location & maxminds).

from django.contrib.gis.geoip import GeoIP2

Also IP address can be extracted by the request.

ip = request.META.get("REMOTE_ADDR")

I was runnning my site on Localhost and had an issue with the above. So as a temporarily solution I did -

ip="72.229.28.185"

This was a random American IP address I found online.

g = GeoIP2()
g.country(ip)

Doing print(g) will give you something like this

{'country_code': 'US', 'country_name': 'United States'}

In your widget constructor, determine the location. Then store the country code as a context variable, like so:

from django.contrib.gis.geoip import GeoIP2

class BootstrapDateTimePickerInput(DateTimeInput):
    template_name = 'widgets/bootstrap_datetimepicker.html'

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super().__init__()

    def get_location(self):
        ip = self.request.META.get("REMOTE_ADDR")
        g = GeoIP2()
        g.country(ip)
        return g

    def get_context(self, name, value, attrs):
        datetimepicker_id = 'datetimepicker_{name}'.format(name=name)
        if attrs is None:
            attrs = dict()
        attrs['data-target'] = '#{id}'.format(id=datetimepicker_id)
        # attrs['data-target'] = '#{id}'.format(id=datetimepicker_id)

        attrs['class'] = 'form-control datetimepicker-input'
        context = super().get_context(name, value, attrs)
        context['widget']['datetimepicker_id'] = datetimepicker_id
        location = self.get_location()
        context['widget']['location'] = location['country_code']
        return context

When I was following Lewis' code I had an error. You can read more about the error here.

TypeError: 'NoneType' object is not subscriptable 

I made the below changes to Lewis' code.

def get_location(self):
    ip = self.request.META.get("REMOTE_ADDR") (or ip="72.229.28.185")
    g = GeoIP2()
    location = g.city(ip)
    location_country = location["country_code"]
    g = location_country
    return g
 
    location = self.get_location()
    context['widget']['location'] = location
    

Then where you define the widget in the form, ensure you pass request into the widget to allow you to utilise it in the widget class thus determining location. Replace <field_name> with the name of the form field.

class YourForm(forms.Form):

    [...]

    def __init__(self, *args, **kwargs):
        request = kwargs.pop('request', None)
        super().__init__(*args, **kwargs)
        self.fields[<field_name>].widget = BootstrapDateTimePickerInput(request=request)

Also in your view you must pass request into the given form:

form = YourForm(request=request)

Finally in the widget just use condition like so:

<script>
  $(function () {
    $("#{{ widget.datetimepicker_id }}").datetimepicker({
      // format: 'DD/MM/YYYY/YYYY HH:mm:ss',


      format: {% if widget.location == 'US' %}'MM/DD/YYYY'{% else %}'DD/MM/YYYY'{% endif %},
      changeYear: true,
      changeMonth: false,
      minDate: new Date("01/01/2015 00:00:00"),
    });
  });
</script>

Extra Question

I need to find a way of telling the back end if the date format is mm/dd/yyyy or dd/mm/yyyy.

  def __init__(self, *args, **kwargs):
    request = kwargs.pop('request', None)
    super().__init__(*args, **kwargs)
    self.fields['d_o_b'].widget = BootstrapDateTimePickerInput(request=request)
    (a) self.fields['d_o_b'].input_formats = ("%d/%m/%Y",)+(self.input_formats)
    (b) self.fields['d_o_b'].widget = BootstrapDateTimePickerInput(request=request, input_formats=['%d/%m/%Y'])
Lewis
  • 1,360
  • 6
  • 18
  • I am getting the error widget=BootstrapDateTimePickerInput(request=request) NameError: name 'request' is not defined – Ross Symonds Aug 11 '20 at 03:40
  • I saw this comment - You are trying to pass the request when constructing the form class. At this point there is no request. The request only exists inside your view function. You should, therefore, pass the request in your view function when constructing the form instance. To prepopulate the form, you can use the initial keyword of the form constructor. It takes a dictionary of field names and values as input. – Ross Symonds Aug 11 '20 at 03:42
  • That’s correct yes, allow me to edit my answer to accommodate for request in form. – Lewis Aug 11 '20 at 06:48
  • I’ve added a section for forms and view code snippets. Also replaced uses of `GeoIP` To `GeoIP2` this was a typo. – Lewis Aug 11 '20 at 07:38
  • I am getting the error message - ip = self.request.META.get("REMOTE_ADDR") AttributeError: 'NoneType' object has no attribute 'META' – Ross Symonds Aug 11 '20 at 14:39
  • I am running the site on localhost, I do not know if that is causing the error. – Ross Symonds Aug 11 '20 at 14:39
  • As a temporarily solution I changed the code to ip="72.229.28.185". Which is a random American IP address I found via Google. And the date widget displayed the American date format. – Ross Symonds Aug 11 '20 at 14:49
  • I then changed the code to ip="86.164.186.201". Which is a random UK IP address I found via Google. And the date widget displayed the UK date format. – Ross Symonds Aug 11 '20 at 14:50
  • I tried other solutions for getting the ip address like 1) ip, is_routable = get_client_ip(request) 2) ip = requests.get('ip.42.pl/raw').text – Ross Symonds Aug 11 '20 at 14:51
  • These solutions worked in views.py but in widgets.py I got the error - name 'request' is not defined – Ross Symonds Aug 11 '20 at 14:51
  • Use self.request in widget. Also yes, this would not work for localhost connection. – Lewis Aug 11 '20 at 15:30