Sunday, July 4, 2021

Django Model what are widgets

A Widget takes care of converting between import and export representations.

This is achieved by the two methods, clean() and render().


clean(valuerow=None*args**kwargs)

Returns an appropriate Python object for an imported value.

For example, if you import a value from a spreadsheet, clean() handles conversion of this value into the corresponding Python object.

Numbers or dates can be cleaned to their respective data types and don’t have to be imported as Strings.



render(valueobj=None)

Returns an export representation of a Python value.

For example, if you have an object you want to export, render() takes care of converting the object’s field to a value that can be written to a spreadsheet.



The different types of available widgets are:


import_export.widgets.IntegerWidget

import_export.widgets.DecimalWidget

import_export.widgets.CharWidget

import_export.widgets.BooleanWidget

import_export.widgets.DateWidget

import_export.widgets.TimeWidget

import_export.widgets.DateTimeWidget

import_export.widgets.DurationWidget

import_export.widgets.JSONWidget

import_export.widgets.ForeignKeyWidget


Unlike specifying a related field in your resource like so

class Meta:

    fields = ('author__name',)



…using a ForeignKeyWidget has the advantage that it can not only be used for exporting, but also importing data with foreign key relationships.


from import_export import fields, resources

from import_export.widgets import ForeignKeyWidget


class BookResource(resources.ModelResource):

    author = fields.Field(

        column_name='author',

        attribute='author',

        widget=ForeignKeyWidget(Author, 'name'))


    class Meta:

        fields = ('author',)



References:

https://django-import-export.readthedocs.io/en/latest/api_widgets.html

Django Model relationship custom through model

The example used in the Django docs is of a Group, Person, and Membership relationship. A group can have many people as members, and a person can be part of many groups, so the Group model has a ManyToManyField that points to Person. Then, a Membership model contains ForeignKeys to both Person and Group, and can store extra information about a person's membership in a specific group, like the date they joined, who invited them, etc.


Using our existing models, we can create all kinds of pizzas with a wide range of toppings. But we can't make a pizza like "Super Pepperoni" that contains double the usual amount of pepperonis. We can't add pepperoni to a pizza more than once:



class ToppingAmount(models.Model):


    REGULAR = 1

    DOUBLE = 2

    TRIPLE = 3

    AMOUNT_CHOICES = (

        (REGULAR, 'Regular'),

        (DOUBLE, 'Double'),

        (TRIPLE, 'Triple'),

    )


    pizza = models.ForeignKey('Pizza', related_name='topping_amounts', on_delete=models.SET_NULL, null=True)

    topping = models.ForeignKey('Topping', related_name='topping_amounts', on_delete=models.SET_NULL, null=True, blank=True)

    amount = models.IntegerField(choices=AMOUNT_CHOICES, default=REGULAR)



Now, add the through option to the toppings field on the Pizza model:

class Pizza(models.Model):

   ...

    toppings = models.ManyToManyField('Topping', through='ToppingAmount', related_name='pizzas')



If specify a through model and does not use it while associating, it will give error 


>> super_pep = Pizza.objects.create(name='Super Pepperoni')

>> pepperoni = Topping.objects.create(name='pepperoni')

>> super_pep.toppings.add(pepperoni)

Traceback (most recent call last):

...

AttributeError: Cannot use add() on a ManyToManyField which specifies an intermediary model. 

Use pizzas.ToppingAmount's Manager instead.



Using a custom "through" model forces us to use that model to associate the pizza and toppings.

super_pep_amount = ToppingAmount.objects.create(pizza=super_pep, topping=pepperoni, amount=ToppingAmount.DOUBLE)


for top_amt in ToppingAmount.objects.filter(pizza=super_pep):

    print(top_amt.topping.name, top_amt.get_amount_display())


pepperoni Double



A through model is also useful for relationships between players and teams; the through model could contain information about the players' positions, jersey numbers, and dates they joined the team. A through model joining movie theatres and films could contain the number of screens the film is showing on and the start and end run dates. Students' relationships to their Degree Programs could track information like GPA, whether the program is the student's major or minor, whether it's a double major, and start/end semesters the student was in a program.





References:

https://www.revsys.com/tidbits/tips-using-djangos-manytomanyfield/#:~:text=The%20example%20used%20in%20the,ManyToManyField%20that%20points%20to%20Person%20.

Django ManyToMany Field

When should you use a ManyToManyField instead of a regular ForeignKey? To remember that, let's think about pizza. A pizza can have many toppings (a Hawaiian pizza usually has Canadian bacon and pineapple), and a topping can go on many pizzas (Canadian bacon also appears on meat lovers' pizzas). Since a pizza can have more than one topping, and a topping can go on more than one pizza, this is a great place to use a ManyToManyField.


from django.db import models 



class Pizza(models.Model):


    name = models.CharField(max_length=30)

    toppings = models.ManyToManyField('Topping')


    def __str__(self):

        return self.name



class Topping(models.Model):


    name = models.CharField(max_length=30)


    def __str__(self):

        return self.name




Both objects must exist in the database

You have to save a Topping in the database before you can add it to a Pizza, and vice versa. This is because a ManyToManyField creates an invisible "through" model that relates the source model (in this case Pizza, which contains the ManyToManyField) to the target model (Topping). In order to create the connection between a pizza and a topping, they both have to be added to this invisible "through" table



Below is what Django Doc says about through relationships 


" [T]here is … an implicit through model class you can use to directly access the table created to hold the association. It has three fields to link the models. If the source and target models differ, the following fields are generated:

  • id: the primary key of the relation.
  • <containing_model>_id: the id of the model that declares the ManyToManyField.
  • <other_model>_id: the id of the model that the ManyToManyField points to."



The invisible "through" model that Django uses to make many-to-many relationships work requires the primary keys for the source model and the target model. A primary key doesn't exist until a model instance is saved, so that's why both instances have to exist before they can be related. (You can't add spinach to your pizza if you haven't bought spinach yet, and you can't add spinach to your pizza if you haven't even started rolling out the crust yet either.)


i.e. below will give error because Topping is not yet saved. 


>> from pizzas.models import Pizza, Topping

>> hawaiian_pizza = Pizza.objects.create(name='Hawaiian')

>> pineapple = Topping(name='pineapple')

>> hawaiian_pizza.toppings.add(pineapple)

Traceback (most recent call last):

...

ValueError: Cannot add "<Topping: pineapple>": instance is on database "default", 

value is on database "None"

>> 



Below will correct this issue 


>> pineapple.save() 

>> hawaiian_pizza.toppings.add(pineapple)

>> hawaiian_pizza.toppings.all()

<QuerySet [<Topping: pineapple>]>



The reverse doesn't work either: I can't create a topping in the database, and then add it to a pizza that hasn't been saved.


>> pepperoni = Topping.objects.create(name='pepperoni')

>> pepperoni_pizza = Pizza(name='Pepperoni')

>> pepperoni_pizza.toppings.add(pepperoni)

Traceback (most recent call last):

...

ValueError: "<Pizza: Pepperoni>" needs to have a value for field "id" before this many-to-many 

relationship can be used.



To retrieve the stuff in a ManyToManyField, you have to use *_set ...

Since the field toppings is already on the Pizza model, getting all the toppings on a specific pizza is pretty straightforward.


That's because Django automatically refers to the target ManyToManyField objects as "sets." The pizzas that use specific toppings are in their own "set":


>> canadian_bacon.pizza_set.all()

<QuerySet [<Pizza: Hawaiian>]>


This can be mitigated by adding a related_name 


Adding the related_name option to a ManyToManyField will let you choose a more intuitive name to use when you want to retrieve the stuff in that field.


class Pizza(models.Model):

    ...

    toppings = models.ManyToManyField('Topping', related_name='pizzas')



The related_name should usually be the lowercase, plural form of your model name. This is confusing for some people because shouldn't the related_name for toppings just be… toppings?


No; the related_name isn't referring to how you want to retrieve the stuff in this field; it specifies the term you want to use instead of *_set when you're on the target object (which in this case is a topping) and want to see which source objects point to that target (what pizzas use a specific topping).

Without a related_name, we would retrieve all the pizzas that use a specific topping with pizza_set:



>> canadian_bacon.pizza_set.all()

<QuerySet [<Pizza: Hawaiian>]>




References:

https://www.revsys.com/tidbits/tips-using-djangos-manytomanyfield/#:~:text=The%20example%20used%20in%20the,ManyToManyField%20that%20points%20to%20Person%20.

SwiftUI how to interact with the backend service and fetch the value

 class LoginManager : ObservableObject {

    @Published var isLoggedIn = false

    

    func doLogin(username: String, password: String) {

        //in here, you'll do your network call

        //I've mocked it with a simple async call for now

        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {

            //set this once you get the correct response from your server

            //this triggers isActive on the NavigationLink below

            self.isLoggedIn = true

        }

    }

}


struct ContentView : View {

    @ObservedObject private var loginManager = LoginManager()

    

    @State var username = ""

    @State var password = ""

    

    var body: some View {

        NavigationView {

            Button(action: {

                loginManager.doLogin(username: username, password: password)

            }) {

                //Login fields...

                Text("Log me in")

            }.overlay(

                NavigationLink(destination: LoggedInView(), isActive: $loginManager.isLoggedIn) {

                    EmptyView()

                }

            )

        }

    }

}


struct LoggedInView : View {

    var body: some View {

        Text("Logged in")

    }

}

references

https://stackoverflow.com/questions/66107887/direct-to-new-view-in-swiftui-after-successful-http-request-login



WebViews in SwiftUI

In order to use a WebView in SwiftUI, we have to build an UIViewRepresentable. Let’s do it.


This below is in ViewModel.swift 


import Foundation

import Combine

class ViewModel: ObservableObject {

    var webViewNavigationPublisher = PassthroughSubject<WebViewNavigation, Never>()

    var showWebTitle = PassthroughSubject<String, Never>()

    var showLoader = PassthroughSubject<Bool, Never>()

    var valuePublisher = PassthroughSubject<String, Never>()

}


// For identifiying WebView's forward and backward navigation

enum WebViewNavigation {

    case backward, forward, reload

}


// For identifying what type of url should load into WebView

enum WebUrlType {

    case localUrl, publicUrl

}



Now can make a coordinator which helps to communicate back and forth with the webview



class Coordinator : NSObject, WKNavigationDelegate {

        var parent: WebView

        var delegate: WebViewHandlerDelegate?

        var valueSubscriber: AnyCancellable? = nil

        var webViewNavigationSubscriber: AnyCancellable? = nil

        

        init(_ uiWebView: WebView) {

            self.parent = uiWebView

            self.delegate = parent

        }

        

        deinit {

            valueSubscriber?.cancel()

            webViewNavigationSubscriber?.cancel()

        }

        

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

            // Get the title of loaded webcontent

            webView.evaluateJavaScript("document.title") { (response, error) in

                if let error = error {

                    print("Error getting title")

                    print(error.localizedDescription)

                }

                

                guard let title = response as? String else {

                    return

                }

                

                self.parent.viewModel.showWebTitle.send(title)

            }

            

            /* An observer that observes 'viewModel.valuePublisher' to get value from TextField and

             pass that value to web app by calling JavaScript function */

            valueSubscriber = parent.viewModel.valuePublisher.receive(on: RunLoop.main).sink(receiveValue: { value in

                let javascriptFunction = "valueGotFromIOS(\(value));"

                webView.evaluateJavaScript(javascriptFunction) { (response, error) in

                    if let error = error {

                        print("Error calling javascript:valueGotFromIOS()")

                        print(error.localizedDescription)

                    } else {

                        print("Called javascript:valueGotFromIOS()")

                    }

                }

            })

            

            // Page loaded so no need to show loader anymore

            self.parent.viewModel.showLoader.send(false)

        }

        

        /* Here I implemented most of the WKWebView's delegate functions so that you can know them and

         can use them in different necessary purposes */

        

        func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {

            // Hides loader

            parent.viewModel.showLoader.send(false)

        }

        

        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {

            // Hides loader

            parent.viewModel.showLoader.send(false)

        }

        

        func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {

            // Shows loader

            parent.viewModel.showLoader.send(true)

        }

        

        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {

            // Shows loader

            parent.viewModel.showLoader.send(true)

            self.webViewNavigationSubscriber = self.parent.viewModel.webViewNavigationPublisher.receive(on: RunLoop.main).sink(receiveValue: { navigation in

                switch navigation {

                    case .backward:

                        if webView.canGoBack {

                            webView.goBack()

                        }

                    case .forward:

                        if webView.canGoForward {

                            webView.goForward()

                        }

                    case .reload:

                        webView.reload()

                }

            })

        }

        

        // This function is essential for intercepting every navigation in the webview

        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

            // Suppose you don't want your user to go a restricted site

            // Here you can get many information about new url from 'navigationAction.request.description'

            if let host = navigationAction.request.url?.host {

                if host == "restricted.com" {

                    // This cancels the navigation

                    decisionHandler(.cancel)

                    return

                }

            }

            // This allows the navigation

            decisionHandler(.allow)

        }

    }



To load data into the webview, below function can do


 func updateUIView(_ webView: WKWebView, context: Context) {

        if url == .localUrl {

            // Load local website

            if let url = Bundle.main.url(forResource: "LocalWebsite", withExtension: "html", subdirectory: "www") {

                webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())

            }

        } else if url == .publicUrl {

            // Load a public website, for example I used here google.com

            if let url = URL(string: "https://www.partners.skyscanner.net/affiliates/widgets-documentation/simple-flight-search-widget") {

                webView.load(URLRequest(url: url))

            }

        }

    }


Below is how to make a WebView


func makeUIView(context: Context) -> WKWebView {

        // Enable javascript in WKWebView

        let preferences = WKPreferences()

        preferences.javaScriptEnabled = true

        

        let configuration = WKWebViewConfiguration()

        // Here "iOSNative" is our delegate name that we pushed to the website that is being loaded

        configuration.userContentController.add(self.makeCoordinator(), name: "iOSNative")

        configuration.preferences = preferences

        

        let webView = WKWebView(frame: CGRect.zero, configuration: configuration)

        webView.navigationDelegate = context.coordinator

        webView.allowsBackForwardNavigationGestures = true

        webView.scrollView.isScrollEnabled = true

       return webView

    }


Now below extension can receive value from WebView 


extension WebView.Coordinator: WKScriptMessageHandler {

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

        // Make sure that your passed delegate is called

        if message.name == "iOSNative" {

            if let body = message.body as? [String: Any?] {

                delegate?.receivedJsonValueFromWebView(value: body)

            } else if let body = message.body as? String {

                delegate?.receivedStringValueFromWebView(value: body)

            }

        }

    }

}


references:

https://blog.devgenius.io/webviews-in-swiftui-d5b1229e37ba

Saturday, July 3, 2021

Postgres explore the data

Once get into the docker container CLI either using the docker view or directly to the CLI 


docker exec -it df6d7538e06917bc2c411b413685710bae819e2fdde735678cd28776d6636a42 /bin/sh


psql -U postgres -W.   


In the above postgres is the user name to the Postgres. This will be usually found in the Django settings files. 

admin  

   

psql -U admin dbname


Once get In, below command  can give the detail of the tables inside 


\dt+


Now to get contents of the DB, usual SQL can be run


Select * from <table_name> 



References:

https://www.postgresqltutorial.com/postgresql-show-tables/

Python Which is faster string concatenation approach

 Python 3.6 changed the game for string concatenation of known components with Literal String Interpolation.


Given the test case from mkoistinen's answer, having strings


domain = 'some_really_long_example.com'

lang = 'en'

path = 'some/really/long/path/'

The contenders are


f'http://{domain}/{lang}/{path}' - 0.151 µs


'http://%s/%s/%s' % (domain, lang, path) - 0.321 µs


'http://' + domain + '/' + lang + '/' + path - 0.356 µs


''.join(('http://', domain, '/', lang, '/', path)) - 0.249 µs (notice that building a constant-length tuple is slightly faster than building a constant-length list).


Thus currently the shortest and the most beautiful code possible is also fastest.


In alpha versions of Python 3.6 the implementation of f'' strings was the slowest possible - actually the generated byte code is pretty much equivalent to the ''.join() case with unnecessary calls to str.__format__ which without arguments would just return self unchanged. These inefficiencies were addressed before 3.6 final.


The speed can be contrasted with the fastest method for Python 2, which is + concatenation on my computer; and that takes 0.203 µs with 8-bit strings, and 0.259 µs if the strings are all Unicode.